<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><script src="https://www.rss.style/js/atom-style.js" xmlns="http://www.w3.org/1999/xhtml"/><title>Tower of Kubes</title><link rel="self" type="application/atom+xml" hreflang="en" href="https://www.towerofkubes.com/tags/til/feed.xml"/><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/tags/til/"/><link rel="alternate" type="application/rss+xml" hreflang="en" href="https://www.towerofkubes.com/tags/til/index.xml"/><id>/</id><updated>2025-11-13T00:00:00Z</updated><author><name>Ro'i Bandel</name></author><generator>Hugo 0.157.0</generator><entry><title>Home Assistant on Kubernetes</title><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/articles/home-assistant-on-k8s/"/><id>https://www.towerofkubes.com/articles/home-assistant-on-k8s/</id><updated>2025-11-13T00:00:00Z</updated><summary type="html">Run Home Assistant on Kubernetes with the Helm chart, covering persistence, add-ons, replicas, and how it compares to Home Assistant OS for homelab smart home deployments.</summary><content type="html"><![CDATA[<p>Today I learned Home Assistant can run on K8s using this Helm Chart: <a href="https://github.com/pajikos/home-assistant-helm-chart"  target="_blank" rel="noreferrer">pajikos/home-assistant-helm-chart: Helm Chart for Home Assistant</a></p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>This Helm chart bootstraps a Home Assistant instance on Kubernetes, supports configurable persistence, controller types, add-ons (e.g. code-server), and is auto-updated with new Home Assistant releases.</p>
      </div>
    </div><ul>
<li><a href="https://t.me/KubeBuilders/1423"  target="_blank" rel="noreferrer">Telegram: View @KubeBuilders</a></li>
</ul>

<h2 class="relative group">My Opinion
    <div id="my-opinion" class="anchor"></div>
    
</h2>
<p>For over two years, I have been running <a href="http://home-assistant.io/"  target="_blank" rel="noreferrer">Home Assistant</a> on <a href="https://www.home-assistant.io/green/"  target="_blank" rel="noreferrer">Home Assistant Green</a>, which comes pre-installed with <a href="https://developers.home-assistant.io/docs/operating-system/"  target="_blank" rel="noreferrer">Home Assistant OS</a>.</p>
<p>The device has been working perfectly well for all of my smart home needs. Even though it is not the most cost-effective way to run Home Assistant, it is a well-designed device, fast enough for my needs and power efficient.</p>
<p>If I were buying a new dedicated device for Home Assistant today, I may have preferred to get a mini PC instead, since some mini PCs are similar in price to the HA Green but significantly more powerful (though maybe not as power efficient). However, I would still strive to run Home Assistant with <a href="https://developers.home-assistant.io/docs/operating-system/"  target="_blank" rel="noreferrer">Home Assistant OS</a>.</p>

<h3 class="relative group">Why standalone device for Home Assistant
    <div id="why-standalone-device-for-home-assistant" class="anchor"></div>
    
</h3>
<p>On recent podcast episodes of Linux Unplugged (including <a href="https://linuxunplugged.com/637"  target="_blank" rel="noreferrer">LINUX Unplugged 637: Chris’ Smart Home Disaster</a>), Chris talked about considering a move away from the Home Assistant Yellow (which is more powerful than the HA Green), perhaps towards a mini PC running multiple services (rather than just a mini PC). Chris also debated the benefits of running Home Assistant on NixOS vs Home Assistant OS. Nevertheless, I tend to agree with Chris’s long-standing stance that it’s best to give Home Assistant its own device, because of how essential it can be to a home.</p>

<h3 class="relative group">Why Home Assistant OS
    <div id="why-home-assistant-os" class="anchor"></div>
    
</h3>
<p>I run all my <em>other</em> self-hosted services in containers. Why not Home Assistant as well? The reason is that <a href="https://developers.home-assistant.io/docs/operating-system/"  target="_blank" rel="noreferrer">Home Assistant OS</a> makes everything easy. Notably, Home Assistant Container installations don’t have access to add-ons.</p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>Add-ons are additional standalone third-party software packages that can be installed on Home Assistant OS. <a href="https://www.home-assistant.io/getting-started/concepts-terminology/#add-ons"  target="_blank" rel="noreferrer">\[Learn more\]</a></p>
      </div>
    </div><ul>
<li><a href="https://www.home-assistant.io/installation/"  target="_blank" rel="noreferrer">Installation - Home Assistant</a></li>
</ul>
<p>Although Add-ons are really just containers, and many Home Assistant users manage to install them as separate containers, this requires elaborate configurations to make the different containers work together with Home Assistant. Even though I’ve been doing Docker Compose stacks (for example, applications that have multiple containers including a database), the moment I found out that HAOS allows one-click installation of Add-ons, I immediately gravitated towards that simplicity. Some examples of Add-ons that I use and rely on are <a href="https://www.home-assistant.io/integrations/matter/"  target="_blank" rel="noreferrer">Matter Server</a>, <a href="https://www.zigbee2mqtt.io/"  target="_blank" rel="noreferrer">Zigbee2MQTT</a> and <a href="https://www.music-assistant.io/"  target="_blank" rel="noreferrer">Music Assistant</a>.</p>
<p>Backups are also fairly simple on HAOS.</p>

<h3 class="relative group">Benefits of the Home Assistant Helm Chart
    <div id="benefits-of-the-home-assistant-helm-chart" class="anchor"></div>
    
</h3>
<p>Nevertheless, I do find the idea of this Home Assistant Helm Chart compelling. Features such as replicas and partial add-ons support make this an interesting alternative to HAOS. I may run a test deployment in my parent’s home, since that’s where my homelab cluster is.</p>
<hr>
<p><em>Featured image by <a href="https://unsplash.com/@jakubzerdzicki?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Jakub Żerdzicki</a> on <a href="https://unsplash.com/photos/a-cell-phone-is-connected-to-a-light-switch-We56jns_zLE?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Unsplash</a>.</em></p>
]]></content><author><name>Ro'i Bandel</name></author><category term="k8s" label="K8s" scheme="https://www.towerofkubes.com/tags/k8s/"/><category term="homeassistant" label="Homeassistant" scheme="https://www.towerofkubes.com/tags/homeassistant/"/><category term="homelab" label="Homelab" scheme="https://www.towerofkubes.com/tags/homelab/"/><category term="smarthome" label="Smarthome" scheme="https://www.towerofkubes.com/tags/smarthome/"/><category term="self-hosted" label="Self-Hosted" scheme="https://www.towerofkubes.com/tags/self-hosted/"/><category term="til" label="Til" scheme="https://www.towerofkubes.com/tags/til/"/><published>2025-11-13T00:00:00Z</published></entry><entry><title>Grebedoc</title><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/articles/grebedoc/"/><id>https://www.towerofkubes.com/articles/grebedoc/</id><updated>2025-11-13T00:00:00Z</updated><summary type="html">Today I learned about Grebedoc — static site hosting for git forges.</summary><content type="html"><![CDATA[<p>Today I learned about <a href="https://grebedoc.dev/"  target="_blank" rel="noreferrer">Grebedoc — static site hosting for git forges</a>.</p>

    <div class="admonition note">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M0 64C0 28.7 28.7 0 64 0L224 0l0 128c0 17.7 14.3 32 32 32l128 0 0 125.7-86.8 86.8c-10.3 10.3-17.5 23.1-21 37.2l-18.7 74.9c-2.3 9.2-1.8 18.8 1.3 27.5L64 512c-35.3 0-64-28.7-64-64L0 64zm384 64l-128 0L256 0 384 128zM549.8 235.7l14.4 14.4c15.6 15.6 15.6 40.9 0 56.6l-29.4 29.4-71-71 29.4-29.4c15.6-15.6 40.9-15.6 56.6 0zM311.9 417L441.1 287.8l71 71L382.9 487.9c-4.1 4.1-9.2 7-14.9 8.4l-60.1 15c-5.5 1.4-11.2-.2-15.2-4.2s-5.6-9.7-4.2-15.2l15-60.1c1.4-5.6 4.3-10.8 8.4-14.9z"/></svg>
        <span>Note</span>
      </div>
      <div class="admonition-content">
        <p>Grebedoc is Codeberg spelled backwards. I find this name very clever, especially since it has “doc” in it (static site hosting can be used for Markdown Documentation|documentation).</p>
      </div>
    </div><p>This is a new option for Static Website Hosting, which can serve as an alternative to GitHub Pages. Codeberg already a similar solution called <a href="https://docs.codeberg.org/codeberg-pages/"  target="_blank" rel="noreferrer">Codeberg Pages</a>, though Codeberg Pages had a big scary warning that says it is in <a href="https://codeberg.org/Codeberg/pages-server/issues/399"  target="_blank" rel="noreferrer">maintenance mode</a>. Grebedoc is using new software, <a href="https://codeberg.org/git-pages/git-pages"  target="_blank" rel="noreferrer">git-pages</a>, so does not rely on <a href="https://codeberg.org/Codeberg"  target="_blank" rel="noreferrer">Codeberg</a>/<a href="https://codeberg.org/Codeberg/pages-server"  target="_blank" rel="noreferrer">pages-server</a> (which is the part of the Codeberg Pages stack that is in maintenance mode).</p>

<h2 class="relative group">Origin Story
    <div id="origin-story" class="anchor"></div>
    
</h2>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>One of Grebedoc maintainers here! I came up with the idea for Grebedoc (and its underlying software, git-pages) when I realized that I have an extreme degree of dependency on GitHub Pages from many years of using GitHub, but it also seemed pretty likely that sooner or later, GitHub will stop subsidizing my efforts one way or another, and I need a backup plan.</p>
<p>I originally wanted to just use Codeberg Pages, but it had some significant scaling and uptime issues (that I don’t want to rehash here). I ended up concluding that the reasonable way forward is a redesign, which is what I’ve built and deployed with a small team of other volunteers. It took about a month of work and the whole thing, anycast and all, costs about 35€/mo to run. Also, Codeberg Pages is currently trialing the use of git-pages as the new pages backend, and you should be able to use it on the *.codeberg.page domain already (it responds to the same POST/PUT requests as Grebedoc)/</p>
      </div>
    </div><ul>
<li><a href="https://lobste.rs/~whitequark"  target="_blank" rel="noreferrer">whitequark</a>’s comment on <a href="https://lobste.rs/c/wmoqsn"  target="_blank" rel="noreferrer">Grebedoc — static site hosting for git forges | Lobsters</a></li>
</ul>
<p>The fact that the entire global stack “costs about 35€/mo to run” is impressive. Though, I wonder what the increase in cost will be when more people start using Grebedoc.</p>

<h2 class="relative group">Can I use Grebedoc for my personal projects?
    <div id="can-i-use-grebedoc-for-my-personal-projects" class="anchor"></div>
    
</h2>
<p>One of my concerns was that Grebedoc sites would <em>have</em> to use a Codeberg repository. Codeberg looks good, though it is more limiting than GitHub or GitLab since <a href="https://docs.codeberg.org/getting-started/faq/#can-i-host-content-without-a-free-and-open-source-license%3F"  target="_blank" rel="noreferrer">they require every repo to use an open source license</a>. This also raises concerns when creating a website/blog of my own, will any content hosted on a Codeberg repo also have to be licensed for the public domain?</p>
<p>However, based on <a href="https://grebedoc.dev/"  target="_blank" rel="noreferrer">grebedoc.dev</a>, using Codeberg is <strong>not</strong> mandatory. There is a small learning curve to understanding how to host a site on Grebedoc, but the main page explains different scenarios clearly. There is a size limitation:</p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>The size of a website is currently limited to <strong>1 GiB</strong>. We are aiming to eventually raise this to 10 GiB.</p>
      </div>
    </div><hr>

    <div class="admonition note">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M0 64C0 28.7 28.7 0 64 0L224 0l0 128c0 17.7 14.3 32 32 32l128 0 0 125.7-86.8 86.8c-10.3 10.3-17.5 23.1-21 37.2l-18.7 74.9c-2.3 9.2-1.8 18.8 1.3 27.5L64 512c-35.3 0-64-28.7-64-64L0 64zm384 64l-128 0L256 0 384 128zM549.8 235.7l14.4 14.4c15.6 15.6 15.6 40.9 0 56.6l-29.4 29.4-71-71 29.4-29.4c15.6-15.6 40.9-15.6 56.6 0zM311.9 417L441.1 287.8l71 71L382.9 487.9c-4.1 4.1-9.2 7-14.9 8.4l-60.1 15c-5.5 1.4-11.2-.2-15.2-4.2s-5.6-9.7-4.2-15.2l15-60.1c1.4-5.6 4.3-10.8 8.4-14.9z"/></svg>
        <span>Note</span>
      </div>
      <div class="admonition-content">
        <p><strong>UPDATE:</strong> Originally, the size limit was 768 MiB, but this has recently been raised to 1 GiB.</p>
      </div>
    </div><p>Based on all of that, it looks like I should be able to host small websites (up to 1 GiB) on Grebedoc, no matter which Git forge I choose to use and the repo can also remain private. I can use my own domains if I want, though Grebedoc also allows using <code>*.grebedoc.dev</code> or <code>*.codeberg.page</code> subdomains. All of this is <strong>free</strong>, as far as I can tell there is no paid-tier (Codeberg is a non-profit, they can be <a href="https://join.codeberg.org/"  target="_blank" rel="noreferrer">supported</a>, but this is not required for using anything they offer).</p>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://grebedoc.dev/"  target="_blank" rel="noreferrer">Grebedoc — static site hosting for git forges</a></li>
<li><a href="https://news.ycombinator.com/item?id=45888143"  target="_blank" rel="noreferrer">Grebedoc – static site hosting for Git forges | Hacker News</a></li>
<li><a href="https://lobste.rs/s/btdj9j/grebedoc_static_site_hosting_for_git"  target="_blank" rel="noreferrer">Grebedoc — static site hosting for git forges | Lobsters</a></li>
<li><a href="https://unterwaditzer.net/2025/codeberg.html"  target="_blank" rel="noreferrer">Moving from GitHub to Codeberg, for lazy people - Markus Unterwaditzer</a></li>
</ul>
<hr>
<p><em>Featured image by <a href="https://unsplash.com/@trolf?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Tina Rolf</a> on <a href="https://unsplash.com/?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Unsplash</a>.</em></p>
]]></content><author><name>Ro'i Bandel</name></author><category term="til" label="Til" scheme="https://www.towerofkubes.com/tags/til/"/><category term="web" label="Web" scheme="https://www.towerofkubes.com/tags/web/"/><category term="website" label="Website" scheme="https://www.towerofkubes.com/tags/website/"/><category term="git" label="Git" scheme="https://www.towerofkubes.com/tags/git/"/><published>2025-11-13T00:00:00Z</published></entry><entry><title>Lima and Colima</title><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/articles/lima-and-colima/"/><id>https://www.towerofkubes.com/articles/lima-and-colima/</id><updated>2025-10-16T00:00:00Z</updated><summary type="html">Overview of Lima and Colima on macOS, how they differ, install commands, Docker usage examples, and Apple’s native Container runtime.</summary><content type="html"><![CDATA[<p>Today I learned about <a href="https://lima-vm.io/"  target="_blank" rel="noreferrer">Lima</a> and <a href="https://github.com/abiosoft/colima"  target="_blank" rel="noreferrer">Colima</a>, which help run Linux VMs and containers on macOS.</p>
<p>I learned about these tools while writing <a href="/articles/how-to-install-docker/" >How To Install Docker</a>. Although I’ve heard about them in the past, I kept forgetting what they were called, which is one reason I am writing about them now.</p>

<h2 class="relative group">Lima
    <div id="lima" class="anchor"></div>
    
</h2>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Lima launches Linux virtual machines with automatic file sharing and port forwarding (similar to WSL2).</span>
      </div>
    </div><ul>
<li><a href="https://lima-vm.io/docs/"  target="_blank" rel="noreferrer">Lima: Linux Machines | Lima</a></li>
</ul>
<p>As this description states, Lima is similar to WSL. When using Windows, I have gotten used to a workflow based around WSL, both <a href="/articles/how-to-install-docker/" >for Docker</a> and <a href="/articles/git-setup-for-windows-and-wsl/" >with Git</a>. I have not used macOS yet but expect to one day get a MacBook as a work laptop, and will have to learn an effective workflow for macOS.</p>

<h2 class="relative group">Colima
    <div id="colima" class="anchor"></div>
    
</h2>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Colima - container runtimes on macOS (and Linux) with minimal setup.</span>
      </div>
    </div><ul>
<li><a href="https://github.com/abiosoft/colima"  target="_blank" rel="noreferrer">GitHub - abiosoft/colima: Container runtimes on macOS (and Linux) with minimal setup</a></li>
</ul>

<h2 class="relative group">Differences between Lima and Colima
    <div id="differences-between-lima-and-colima" class="anchor"></div>
    
</h2>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>How does Colima compare to Lima?</span>
      </div>
      <div class="admonition-content">
        <p>Colima is basically a higher level usage of Lima and utilises Lima to provide Docker, Containerd and/or Kubernetes.</p>
      </div>
    </div><ul>
<li><a href="https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#how-does-colima-compare-to-lima"  target="_blank" rel="noreferrer">colima/docs/FAQ.md at main · abiosoft/colima · GitHub</a></li>
</ul>
<hr>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>“How does Lima relate to Colima?”</span>
      </div>
      <div class="admonition-content">
        <p><a href="https://github.com/abiosoft/colima"  target="_blank" rel="noreferrer">Colima</a> is a third-party project that wraps Lima to provide an alternative user experience for launching containers.</p>
<p>The key difference is that Colima launches Docker by default, while Lima launches containerd by default.</p>
      </div>
    </div><ul>
<li><a href="https://lima-vm.io/docs/faq/colima/"  target="_blank" rel="noreferrer">Colima (third-party project) | Lima</a></li>
</ul>
<p>It’s worth noting that current versions of Lima also support <a href="https://lima-vm.io/docs/examples/containers/docker/"  target="_blank" rel="noreferrer">using Docker as a container runtime</a>, and the same is true the other way: Colima supports <a href="https://github.com/abiosoft/colima?tab=readme-ov-file#containerd"  target="_blank" rel="noreferrer">using containerd as a container runtime</a>.</p>

<h2 class="relative group">Installation
    <div id="installation" class="anchor"></div>
    
</h2>

<h3 class="relative group">Install Lima
    <div id="install-lima" class="anchor"></div>
    
</h3>
<ul>
<li><a href="https://lima-vm.io/docs/installation/"  target="_blank" rel="noreferrer">Installation | Lima</a></li>
</ul>

    <div class="admonition example">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M192 96a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm-8 384l0-128 16 0 0 128c0 17.7 14.3 32 32 32s32-14.3 32-32l0-288 56 0 64 0 16 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-16 0 0-64 192 0 0 192-192 0 0-32-64 0 0 48c0 26.5 21.5 48 48 48l224 0c26.5 0 48-21.5 48-48l0-224c0-26.5-21.5-48-48-48L368 0c-26.5 0-48 21.5-48 48l0 80-76.9 0-65.9 0c-33.7 0-64.9 17.7-82.3 46.6l-58.3 97c-9.1 15.1-4.2 34.8 10.9 43.9s34.8 4.2 43.9-10.9L120 256.9 120 480c0 17.7 14.3 32 32 32s32-14.3 32-32z"/></svg>
        <span>Example</span>
      </div>
      <div class="admonition-content">
        <div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Homebrew</span>
</span></span><span class="line"><span class="cl">brew install lima</span></span></code></pre></div></div>
<hr>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># MacPorts</span>
</span></span><span class="line"><span class="cl">sudo port install lima</span></span></code></pre></div></div>
<hr>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Nix</span>
</span></span><span class="line"><span class="cl">nix-env -i lima</span></span></code></pre></div></div>
      </div>
    </div>
<h3 class="relative group">Install Colima
    <div id="install-colima" class="anchor"></div>
    
</h3>
<p>Colima is available on Homebrew, MacPorts, and Nix. <a href="https://github.com/abiosoft/colima/blob/main/docs/INSTALL.md"  target="_blank" rel="noreferrer">Check here for other installation options</a>.</p>

    <div class="admonition example">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M192 96a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm-8 384l0-128 16 0 0 128c0 17.7 14.3 32 32 32s32-14.3 32-32l0-288 56 0 64 0 16 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-16 0 0-64 192 0 0 192-192 0 0-32-64 0 0 48c0 26.5 21.5 48 48 48l224 0c26.5 0 48-21.5 48-48l0-224c0-26.5-21.5-48-48-48L368 0c-26.5 0-48 21.5-48 48l0 80-76.9 0-65.9 0c-33.7 0-64.9 17.7-82.3 46.6l-58.3 97c-9.1 15.1-4.2 34.8 10.9 43.9s34.8 4.2 43.9-10.9L120 256.9 120 480c0 17.7 14.3 32 32 32s32-14.3 32-32z"/></svg>
        <span>Example</span>
      </div>
      <div class="admonition-content">
        <div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Homebrew</span>
</span></span><span class="line"><span class="cl">brew install colima</span></span></code></pre></div></div>
<hr>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># MacPorts</span>
</span></span><span class="line"><span class="cl">sudo port install colima</span></span></code></pre></div></div>
<hr>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Nix</span>
</span></span><span class="line"><span class="cl">nix-env -iA nixpkgs.colima</span></span></code></pre></div></div>
      </div>
    </div>
<h2 class="relative group">Using Docker with Lima and Colima
    <div id="using-docker-with-lima-and-colima" class="anchor"></div>
    
</h2>

<h3 class="relative group">Docker with Lima
    <div id="docker-with-lima" class="anchor"></div>
    
</h3>
<p><a href="https://lima-vm.io/docs/examples/containers/docker/"  target="_blank" rel="noreferrer">Documentation / Examples / Containers / Docker | Lima</a></p>

<h4 class="relative group">Lima Docker Rootless
    <div id="lima-docker-rootless" class="anchor"></div>
    
</h4>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">limactl start template://docker
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">DOCKER_HOST</span><span class="o">=</span><span class="k">$(</span>limactl list docker --format <span class="s1">'unix://{{.Dir}}/sock/docker.sock'</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">docker run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine</span></span></code></pre></div></div>

<h4 class="relative group">Lima Docker Rootful
    <div id="lima-docker-rootful" class="anchor"></div>
    
</h4>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">limactl start template://docker-rootful
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">DOCKER_HOST</span><span class="o">=</span><span class="k">$(</span>limactl list docker-rootful --format <span class="s1">'unix://{{.Dir}}/sock/docker.sock'</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">docker run -d --name nginx -p 127.0.0.1:8080:80 nginx:alpine</span></span></code></pre></div></div>

<h3 class="relative group">Docker with Colima
    <div id="docker-with-colima" class="anchor"></div>
    
</h3>
<p>Docker client is required for Docker runtime. Installable with brew <code>brew install docker</code>.</p>
<p>You can use the <code>docker</code> client on macOS after <code>colima start</code> with no additional setup.</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">brew install docker
</span></span><span class="line"><span class="cl">colima start</span></span></code></pre></div></div>

<h2 class="relative group">Linux Support
    <div id="linux-support" class="anchor"></div>
    
</h2>
<p><strong>Both run on Linux hosts.</strong> Lima also supports <a href="https://github.com/lima-vm/lima?tab=readme-ov-file#lima-linux-machines"  target="_blank" rel="noreferrer">non-macOS hosts (Linux, NetBSD, etc.)</a> and <a href="https://github.com/abiosoft/colima?tab=readme-ov-file#features"  target="_blank" rel="noreferrer">Colima’s README lists Linux as supported</a>.</p>
<p>There’s less reason to use Lima/Colima on Linux than on macOS, but it may still be useful in certain cases, since it is another way to run VMs on Linux.</p>

<h2 class="relative group">Apple Container
    <div id="apple-container" class="anchor"></div>
    
</h2>
<p>After years of mac users using projects such as Lima, Colima and others in order to run containers on macOS, Apple released their own solution a few months ago: <a href="https://opensource.apple.com/projects/container/"  target="_blank" rel="noreferrer">Container</a>. This seems like a good solution that likely has good performance. Notably, this solution is not based on Docker, but can nevertheless run OCI containers.</p>
<hr>
<p><em>Featured image by <a href="https://unsplash.com/@creatorsproduce?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Aarom Ore</a> on <a href="https://unsplash.com/photos/city-on-island-during-day-Yrqyn1Gb80k?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Unsplash</a>.</em></p>
]]></content><author><name>Ro'i Bandel</name></author><category term="tools" label="Tools" scheme="https://www.towerofkubes.com/tags/tools/"/><category term="container" label="Container" scheme="https://www.towerofkubes.com/tags/container/"/><category term="til" label="Til" scheme="https://www.towerofkubes.com/tags/til/"/><category term="snippets" label="Snippets" scheme="https://www.towerofkubes.com/tags/snippets/"/><category term="guide" label="Guide" scheme="https://www.towerofkubes.com/tags/guide/"/><published>2025-10-16T00:00:00Z</published></entry><entry><title>Diátaxis framework for technical documentation</title><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/articles/diataxis/"/><id>https://www.towerofkubes.com/articles/diataxis/</id><updated>2025-10-05T00:00:00Z</updated><summary type="html">Overview of the Diátaxis documentation framework: tutorials, how-to guides, reference, and explanation, and when to use it for clearer tech docs.</summary><content type="html"><![CDATA[<p>Today I learned about <a href="https://diataxis.fr"  target="_blank" rel="noreferrer">Diátaxis</a>, a framework for technical documentation.</p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>Diátaxis is a way of thinking about and doing documentation.
It prescribes approaches to content, architecture and form that emerge from a systematic approach to understanding the needs of documentation users.</p>
<p>Diátaxis identifies four distinct needs, and four corresponding forms of documentation - <em>tutorials</em>, <em>how-to guides</em>, <em>technical reference</em> and <em>explanation</em>. It places them in a systematic relationship, and proposes that documentation should itself be organised around the structures of those needs.</p>
<figure><img
    class="my-0 rounded-md"
    loading="lazy"
    decoding="async"
    fetchpriority="low"
    alt="Diátaxis"
    src="https://diataxis.fr/_images/diataxis.png"
    ></figure>
<p>Diátaxis solves problems related to documentation <em>content</em> (what to write), <em>style</em> (how to write it) and <em>architecture</em> (how to organise it).</p>
<p>As well as serving the users of documentation, Diátaxis has value for documentation creators and maintainers. It is light-weight, easy to grasp and straightforward to apply. It doesn’t impose implementation constraints. It brings an active principle of quality to documentation that helps maintainers think effectively about their own work.</p>
      </div>
    </div>
<h2 class="relative group">I Need To Write Documentation
    <div id="i-need-to-write-documentation" class="anchor"></div>
    
</h2>
<p>I’ve been thinking a lot about documentation recently, experimenting with software such as Material for MkDocs and Docusaurus. These frameworks solve the problems of <em>how</em> and <em>where</em> to write documentation (Markdown files served as a static site by one of these frameworks together with <a href="/series/static-website-hosting/" >static website hosting</a>). However, they don’t solve the much more important problem of <em>what</em> to write about. There’s an entire field of <a href="https://en.wikipedia.org/wiki/Technical_writing"  target="_blank" rel="noreferrer"><strong>technical writing</strong></a>.</p>
<p>I am now in a situation where I need to write several pieces of documentation. My client requested I create documentation for them based on what I’m working on, to both on-board new users/developers on how to work on the codebase and run pipelines, as well as two explain in-depth to any future DevOps Engineers or admins about how I set up our cloud infrastructure, repositories, custom tools and pipelines. Two pieces of documentation are needed. For the client, I will use <a href="https://www.atlassian.com/software/confluence"  target="_blank" rel="noreferrer">Confluence</a>; <a href="/articles/bitbucket-vs-the-competition/" >I am not a fan of Atlassian</a>, but the alternative for this client is to write Word documents. Confluence will do. Besides, I’m not going to setup Docusaurus for this client.</p>
<p>At the same time, I also want to write documentation for my “homelab-as-code” project and to help write documentation for <a href="https://docs.calme.win/"  target="_blank" rel="noreferrer">CALMe</a> (together with Josh, who works as a technical writer).</p>

<h2 class="relative group">Diátaxis
    <div id="diátaxis" class="anchor"></div>
    
</h2>
<p>I learned about <a href="https://diataxis.fr"  target="_blank" rel="noreferrer">Diátaxis</a> from Khue’s Homelab: <a href="https://homelab.khuedoan.com/how-to-guides/updating-documentation/"  target="_blank" rel="noreferrer">Updating documentation (this website) - Khue’s Homelab</a></p>
<p><a href="https://homelab.khuedoan.com/"  target="_blank" rel="noreferrer">Khue’s Homelab</a> is one of the most impressive homelab projects that I’ve seen. “Fully automated homelab from empty disk to running services with a single command”. It is also well documented. It uses the <a href="https://diataxis.fr"  target="_blank" rel="noreferrer">Diátaxis</a> technical documentation framework:</p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>There are 4 main parts:</p>
<ul>
<li><a href="https://diataxis.fr/tutorials"  target="_blank" rel="noreferrer">Getting started (tutorials)</a>: learning-oriented</li>
<li><a href="https://diataxis.fr/explanation"  target="_blank" rel="noreferrer">Concepts (explanation)</a>: understanding-oriented</li>
<li><a href="https://diataxis.fr/how-to-guides"  target="_blank" rel="noreferrer">How-to guides</a>: goal-oriented</li>
<li><a href="https://diataxis.fr/reference"  target="_blank" rel="noreferrer">Reference</a>: information-oriented</li>
</ul>
      </div>
    </div><p><strong>These four parts are the basis of Diátaxis:</strong></p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>At the core of Diátaxis are the four different kinds of documentation it identifies. If you’re encountering Diátaxis for the first time, start with these pages.</p>
<ul>
<li>
<p><a href="https://diataxis.fr/tutorials/"  target="_blank" rel="noreferrer">Tutorials</a> - learning-oriented experiences</p>
</li>
<li>
<p><a href="https://diataxis.fr/how-to-guides/"  target="_blank" rel="noreferrer">How-to guides</a> - goal-oriented directions</p>
</li>
<li>
<p><a href="https://diataxis.fr/reference/"  target="_blank" rel="noreferrer">Reference</a> - information-oriented technical description</p>
</li>
<li>
<p><a href="https://diataxis.fr/explanation/"  target="_blank" rel="noreferrer">Explanation</a> - understanding-oriented discussion</p>
</li>
</ul>
<p>Diátaxis prescribes principles that guide action. These translate into particular ways of working, with implications for documentation process and execution. Once you’ve made your first start, the tools and methods outlined here will help smooth your way.</p>
<ul>
<li>
<p><a href="https://diataxis.fr/compass/"  target="_blank" rel="noreferrer">The compass</a> - a simple tool for direction-finding</p>
</li>
<li>
<p><a href="https://diataxis.fr/how-to-use-diataxis/"  target="_blank" rel="noreferrer">Workflow</a> in Diátaxis</p>
</li>
</ul>
      </div>
    </div>
<h2 class="relative group">Should I Adopt Diátaxis?
    <div id="should-i-adopt-diátaxis" class="anchor"></div>
    
</h2>
<p>On first impressions Diátaxis looks great. Writing it may be somewhat challenging at first as I learn to structure technical writing in this way, but the results may well be worth it. I am having a hard time finding alternative documentation frameworks (though I’m sure they exist). The alternative for me to using Diátaxis would be free-flow documentation based on the topics that I think I should cover; this is how I have been writing documentation until now which does work but may end up a bit messy. Of course, Diátaxis is not perfect either and there are criticisms for it: <a href="https://www.hillelwayne.com/post/problems-with-the-4doc-model/"  target="_blank" rel="noreferrer">My Problem With the Four-Document Model</a>.</p>
<hr>
<p><em>Featured image by <a href="https://unsplash.com/@sigmund?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Sigmund</a> on <a href="https://unsplash.com/photos/a-screen-with-a-bunch-of-information-on-it-cdMAU_x9mxY?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Unsplash</a>.</em></p>
]]></content><author><name>Ro'i Bandel</name></author><category term="docs" label="Docs" scheme="https://www.towerofkubes.com/tags/docs/"/><category term="homelab" label="Homelab" scheme="https://www.towerofkubes.com/tags/homelab/"/><category term="til" label="Til" scheme="https://www.towerofkubes.com/tags/til/"/><published>2025-10-05T00:00:00Z</published></entry><entry><title>Bitbucket versus the Competition</title><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/articles/bitbucket-vs-the-competition/"/><id>https://www.towerofkubes.com/articles/bitbucket-vs-the-competition/</id><updated>2025-09-30T00:00:00Z</updated><summary type="html">Comparison of Bitbucket vs. GitHub vs. GitLab</summary><content type="html"><![CDATA[<p>TIL that Bitbucket is the slowest of the major software forges according to <a href="https://forgeperf.org/"  target="_blank" rel="noreferrer">Software Forge Performance Index</a>.</p>
<p><a href="https://forgeperf.org/"  target="_blank" rel="noreferrer">forgeperf.org</a> is maintained by SourceHut, who are not impartial. SourceHut just so happen to lead most of the performance results. I can believe that the benchmarks are accurate, though the benchmarks may have been designed in a way that favors SourceHut.</p>
<p>Even so, performance is not everything. SourceHut’s UI is noticeably basic, which might be good for performance but not necessarily the most pleasent to use. SH patchsets are sent over email, an antiquated workflow (even if it’s still how Linux kernel development works).</p>
<p>The reasons I dislike Bitbucket have little to do with its subpar performance. Bitbucket, like most of Atlassian’s suite, just feels <em>aggressively average</em>. I wouldn’t go as far as to say Bitbucket is <em>bad</em>, it functions fine as a git forge. It does the basics decently well and many enterprises successfully use it. However, when compared to its main competitors, Bitbucket feels objectively worse. It kind of sucks.</p>

<h2 class="relative group">The Competition
    <div id="the-competition" class="anchor"></div>
    
</h2>
<p>I would consider the main competitors to be GitHub and GitLab. Both of these have many more features than Bitbucket. Bitbucket is falling behind and playing catch-up, slowly implementing features that the competitors had <em>years</em> ago. Here are several examples.</p>

<h3 class="relative group">Artifact Registry
    <div id="artifact-registry" class="anchor"></div>
    
</h3>
<p>There was a recent announcement of <a href="https://www.atlassian.com/blog/bitbucket/coming-soon-bitbucket-packages"  target="_blank" rel="noreferrer">Bitbucket Packages</a>. This will be Bitbucket’s own solution for an artifact registry, starting with a container registry. GitHub and GitLab already had artifact registry solutions for <em>years</em>, for example GitHub launched <a href="https://github.blog/news-insights/product-news/introducing-github-package-registry/"  target="_blank" rel="noreferrer">GitHub Package Registry in 2019</a> and <a href="https://github.blog/news-insights/product-news/github-packages-container-registry-generally-available/"  target="_blank" rel="noreferrer">GitHub Container Registry in 2021</a>. Even when Bitbucket Packages does launch it will be limited to containers only at first. I also noticed that Bitbucket is missing a Releases feature, which both <a href="https://github.blog/news-insights/product-news/github-packages-container-registry-generally-available/"  target="_blank" rel="noreferrer">GitHub</a> and <a href="https://docs.gitlab.com/user/project/releases/"  target="_blank" rel="noreferrer">GitLab</a> have.</p>

<h3 class="relative group">CI/CD
    <div id="cicd" class="anchor"></div>
    
</h3>
<p>Atlassian has had several different CI/CD solutions over the years. Bamboo used to be the main one, and many companies used (or still use) a Bitbucket+Jenkins combo. Nowadays, Bitbucket Pipelines is the main solution that Atlassian tries to push onto its customers. One of these customers is my current client. I came into the client having to deal with the hacky Bitbucket pipelines that the previous team left me. We are using self-hosted Bitbucket Runners running on EC2 instances, because the hosted Bitbucket Runners are underpowered. Overall, I got the pipeline working, although the entire time I wished I was using GitHub Actions instead. To be fair, it’s clear Bitbucket Pipelines is being actively developed and is getting new features. However, it’s also clear that it’s playing catch-up against others CI/CD solutions (including GHA and GitLab CI/CD). There are all sorts of weird limitations, some of which have been fixed and others which still haven’t. For example, until recently, <a href="https://blog.devops.dev/breaking-the-2-hour-pipeline-barrier-a-bitbucket-cloud-saga-9780b1bfa7e9"  target="_blank" rel="noreferrer">Bitbucket Pipeline steps were limited to only 2 hours</a>. This has thankfully been fixed, and now the <a href="https://support.atlassian.com/bitbucket-cloud/docs/global-options/#Max-time"  target="_blank" rel="noreferrer"><code>max-time</code></a> can be set up to <code>720</code> (12 hours), enough to most (but not all) jobs. Other limitations continue to exist. GitHub has the <a href="https://github.com/marketplace?type=actions"  target="_blank" rel="noreferrer">Actions Marketplace</a> full of community actions that can be easily integrated into GHA workflows, often completely for free (many actions are FOSS). Bitbucket works with the <a href="https://marketplace.atlassian.com/product/bitbucket"  target="_blank" rel="noreferrer">Atlassian Marketplace</a> and <a href="https://bitbucket.org/product/features/pipelines/integrations"  target="_blank" rel="noreferrer">Bitbucket Pipes integrations | Bitbucket</a>, but this is much more limited and harder to use with Pipelines, and the majority of Apps are paid.</p>

<h3 class="relative group">SSH commit signature verification
    <div id="ssh-commit-signature-verification" class="anchor"></div>
    
</h3>
<p>I was excited about SSH commit signature verification this feature when I learned about it during my bootcamp in late 2022. <a href="https://github.blog/changelog/2022-08-23-ssh-commit-verification-now-supported/"  target="_blank" rel="noreferrer">GitHub was quick to implement it</a> and <a href="https://about.gitlab.com/releases/2022/12/22/gitlab-15-7-released/"  target="_blank" rel="noreferrer">GitLab not long after</a>. I then started working with clients that used Bitbucket and was surprised to find this feature missing! Only in <a href="https://www.atlassian.com/blog/bitbucket/you-can-now-sign-commits-with-ssh-keys"  target="_blank" rel="noreferrer">2025 did Bitbucket Cloud release SSH commit signature verification</a>, more than two years after both GitHub and GitLab.</p>

<h3 class="relative group">Bitbucket CLI
    <div id="bitbucket-cli" class="anchor"></div>
    
</h3>
<p>Bitbucket has <strong>no</strong> official CLI tool in the style of <a href="https://cli.github.com/"  target="_blank" rel="noreferrer">GitHub CLI</a> or <a href="https://gitlab.com/gitlab-org/cli"  target="_blank" rel="noreferrer">GitLab CLI</a>. Of course, the standarad Git CLI does work well with Bitbucket, but the <code>gh</code> and <code>glab</code> CLI tools go beyond that and allow to do many actions directly using commands. Bitbucket does have REST APIs (<a href="https://developer.atlassian.com/server/bitbucket/rest/"  target="_blank" rel="noreferrer">The Bitbucket Data Center REST API</a> and <a href="https://developer.atlassian.com/cloud/bitbucket/rest/"  target="_blank" rel="noreferrer">The Bitbucket Cloud REST API</a>) which do work, but are harder to use than an equivalent CLI tool would be.</p>

<h3 class="relative group">Cloud Development Environments
    <div id="cloud-development-environments" class="anchor"></div>
    
</h3>
<p>GitHub has <a href="https://docs.github.com/en/codespaces"  target="_blank" rel="noreferrer">Codespaces</a> and GitLab has <a href="https://docs.gitlab.com/user/workspace/"  target="_blank" rel="noreferrer">Workspaces</a>. Both are Cloud Development Environments based on VS Code. Microsoft maintains both GitHub and VS Code. VS Code itself remains open source under the <a href="https://github.com/microsoft/vscode?tab=MIT-1-ov-file#readme"  target="_blank" rel="noreferrer">MIT license</a>. GitLab maintains their own <a href="https://gitlab.com/gitlab-org/gitlab-web-ide-vscode-fork"  target="_blank" rel="noreferrer">VS Code fork</a>.</p>
<p>Bitbucket offers to use <a href="https://support.atlassian.com/bitbucket-cloud/docs/install-cloud-ide-add-ons/"  target="_blank" rel="noreferrer">Cloud IDE add-ons</a> <a href="https://bitbucket.org/integrations/cloud"  target="_blank" rel="noreferrer">Bitbucket Integrations</a>, but doesn’t have anything built-in.</p>

<h3 class="relative group">Automatic Dependency Updates
    <div id="automatic-dependency-updates" class="anchor"></div>
    
</h3>
<p><a href="https://github.com/dependabot"  target="_blank" rel="noreferrer">Dependabot</a> is built into GitHub. GitLab uses <a href="https://gitlab.com/gitlab-org/frontend/renovate-gitlab-bot"  target="_blank" rel="noreferrer">Renovate GitLab Bot</a>. Renovatebot can work with Bitbucket, either self-hosted or supported by Mend, however there is nothing built-in to Bitbucket.</p>

<h3 class="relative group">Fragmented Hosting Solutions
    <div id="fragmented-hosting-solutions" class="anchor"></div>
    
</h3>
<p>A major point of confusion for me when using Bitbucket has been the the differences between Bitbucket Data Center and Bitbucket Cloud. While both look like Bitbucket, they are essentially two different products with different features and development cycles. Every time I look up Bitbucket documentation, I have to make sure that I am following docs for the right product. There are even two different Bitbucket REST APIs.</p>
<p>In comparison, GitLab operates <a href="https://about.gitlab.com/blog/2019/08/23/a-single-codebase-for-gitlab-community-and-enterprise-edition/"  target="_blank" rel="noreferrer">under a single codebase for Community and Enterprise editions</a> and the same codebase is used to run GitLab.com:</p>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p>The largest known GitLab instance is on GitLab.com, which is deployed using our <a href="https://docs.gitlab.com/charts/"  target="_blank" rel="noreferrer">official GitLab Helm chart</a> and the <a href="https://about.gitlab.com/install/"  target="_blank" rel="noreferrer">official Linux package</a>.</p>
      </div>
    </div><ul>
<li><a href="https://docs.gitlab.com/development/architecture/"  target="_blank" rel="noreferrer">GitLab architecture overview | GitLab Docs</a></li>
</ul>

<h3 class="relative group">Bitbucket Kills Self-Hosting
    <div id="bitbucket-kills-self-hosting" class="anchor"></div>
    
</h3>
<p><a href="https://www.atlassian.com/licensing/server-end-of-support#what-does-end-of-support-mean"  target="_blank" rel="noreferrer">Bitbucket Server reached end of support in 2024</a>. My clients at the time were already using Bitbucket Data Center so they weren’t affected. However, Bitbucket recently announced that Data Center will reach end of life in 2029. The solution going forward will be <strong>only</strong> Bitbucket Cloud. While this solves the fragmentation problem, it does so at the expanse of any self-hosted solutions. I believe there are still organizations for whom self-hosting is non-negotiable. Atlassian is essentially giving up on these customers. Perhaps they’ve done their cold calculations and decided that continuing to develop and support Bitbucket Data Center is no longer worth it even if they do lose some customers.</p>
<p>Meanwhile, GitLab continues to to offer a self-hosted solution, that can even run for free with <a href="https://gitlab.com/rluna-gitlab/gitlab-ce"  target="_blank" rel="noreferrer">GitLab Community Edition</a>. GitHub offers <a href="https://docs.github.com/en/enterprise-server@3.14/admin/overview/about-github-enterprise-server"  target="_blank" rel="noreferrer">GitHub Enterprise Server</a>.</p>
<hr>
<p><em>Featured image by <a href="https://unsplash.com/@courtneyam98?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Courtney Moore</a> on <a href="https://unsplash.com/?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Unsplash</a>.</em></p>
]]></content><author><name>Ro'i Bandel</name></author><category term="til" label="Til" scheme="https://www.towerofkubes.com/tags/til/"/><category term="git" label="Git" scheme="https://www.towerofkubes.com/tags/git/"/><published>2025-09-30T00:00:00Z</published></entry><entry><title>KYAML</title><link rel="alternate" type="text/html" hreflang="en" href="https://www.towerofkubes.com/articles/kyaml/"/><id>https://www.towerofkubes.com/articles/kyaml/</id><updated>2025-08-11T00:00:00Z</updated><summary type="html">Today I learned, in Kubernetes v1.34, kubectl will also support a new strict subset of YAML called KYAML.</summary><content type="html"><![CDATA[<p>Today I learned, in Kubernetes v1.34, <code>kubectl</code> will also support a new strict subset of YAML called KYAML.</p>

<h2 class="relative group">Resources
    <div id="resources" class="anchor"></div>
    
</h2>
<ul>
<li><a href="https://kubernetes.io/blog/2025/07/28/kubernetes-v1-34-sneak-peek/#support-for-kyaml-a-kubernetes-dialect-of-yaml"  target="_blank" rel="noreferrer">Support for KYAML: a Kubernetes dialect of YAML | Kubernetes v1.34 Sneak Peek | Kubernetes</a></li>
<li><a href="https://thenewstack.io/kubernetes-is-getting-a-better-yaml/"  target="_blank" rel="noreferrer">Kubernetes Will Solve YAML Headaches with KYAML - The New Stack</a></li>
<li><a href="https://medium.com/@simardeep.oberoi/kyaml-kubernetes-answer-to-yaml-s-configuration-chaos-0c0c09f51587"  target="_blank" rel="noreferrer">KYAML: Kubernetes’ Answer to YAML’s Configuration Chaos | by Simardeep Singh | Aug, 2025 | Medium</a></li>
<li><a href="https://kubernetes.io/blog/2025/08/27/kubernetes-v1-34-release/#alpha-support-for-kyaml-a-kubernetes-dialect-of-yaml"  target="_blank" rel="noreferrer">Kubernetes v1.34: Of Wind & Will (O’ WaW)</a></li>
</ul>

<h2 class="relative group">Shell Script
    <div id="shell-script" class="anchor"></div>
    
</h2>
<p>I coded a simple script to convert all Kubernetes manifests in a directory from YAML to KYAML.</p>
<p>Initially, I wanted to code my own converter, but then found out that the upstream Kubernetes project already has a new yamlfmt tool (different from <a href="https://github.com/google/yamlfmt"  target="_blank" rel="noreferrer">google/yamlfmt</a>).</p>
<div class="highlight-wrapper"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="cl"><span class="c1"># kyamlify.sh — Rename *.yaml -> *.kyaml then format to KYAML (POSIX)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Usage: ./kyamlify.sh [ROOT_DIR]</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Env: YAMLFMT_VERSION (default: master)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -eu
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">ROOT_DIR</span><span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">1</span><span class="k">:-</span><span class="nv">kubernetes</span><span class="si">}</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl"><span class="nv">YAMLFMT_VERSION</span><span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">YAMLFMT_VERSION</span><span class="k">:-</span><span class="nv">master</span><span class="si">}</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Require Go</span>
</span></span><span class="line"><span class="cl"><span class="nb">command</span> -v go >/dev/null 2><span class="p">&</span><span class="m">1</span> <span class="o">||</span> <span class="o">{</span> <span class="nb">echo</span> <span class="s2">"error: Go not found in PATH"</span> ><span class="p">&</span>2<span class="p">;</span> <span class="nb">exit</span> 1<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">"→ Installing yamlfmt @ </span><span class="nv">$YAMLFMT_VERSION</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl">go install <span class="s2">"sigs.k8s.io/yaml/yamlfmt@</span><span class="si">${</span><span class="nv">YAMLFMT_VERSION</span><span class="si">}</span><span class="s2">"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">"→ Formatting all YAML files under </span><span class="si">${</span><span class="nv">ROOT_DIR</span><span class="si">}</span><span class="s2"> as KYAML"</span>
</span></span><span class="line"><span class="cl">find <span class="s2">"</span><span class="si">${</span><span class="nv">ROOT_DIR</span><span class="si">}</span><span class="s2">"</span> -type f -name <span class="s1">'*.yaml'</span> -print0 <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="p">|</span> xargs -0 -n1 <span class="s2">"</span><span class="k">$(</span>go env GOPATH<span class="k">)</span><span class="s2">/bin/yamlfmt"</span> -o kyaml -w</span></span></code></pre></div></div>

<h2 class="relative group">KYAML Rules
    <div id="kyaml-rules" class="anchor"></div>
    
</h2>

    <div class="admonition quote">
      <div class="admonition-header"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 296c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72zm-256 0c0 66.3-53.7 120-120 120l-8 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l8 0c30.9 0 56-25.1 56-56l0-8-64 0c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l64 0c35.3 0 64 28.7 64 64l0 32 0 32 0 72z"/></svg>
        <span>Quote</span>
      </div>
      <div class="admonition-content">
        <p><a href="https://kep.k8s.io/5295"  target="_blank" rel="noreferrer">KEP-5295</a> introduces KYAML, which tries to address the most significant problems by:</p>
<ul>
<li>Always double-quoting value strings</li>
<li>Leaving keys unquoted unless they are potentially ambiguous</li>
<li>Always using <code>{}</code> for mappings (associative arrays)</li>
<li>Always using <code>[]</code> for lists</li>
</ul>
      </div>
    </div><ul>
<li><a href="https://kubernetes.io/blog/2025/07/28/kubernetes-v1-34-sneak-peek/#support-for-kyaml-a-kubernetes-dialect-of-yaml"  target="_blank" rel="noreferrer">Support for KYAML: a Kubernetes dialect of YAML | Kubernetes v1.34 Sneak Peek | Kubernetes</a></li>
</ul>
<p>These rules are similar in practice to <a href="https://json5.org/"  target="_blank" rel="noreferrer">JSON5</a>. However, while JSON5 is a <em>superset</em> of JSON (as well as a <em>subset</em> of ES5), KYAML is a <em>subset</em> of YAML.</p>
<p>In fact, I suspect that by adding <code>---</code> to the first line of a JSON5 file, it would be valid KYAML.</p>
<p>By the way, starting the file with <code>---</code> is <strong>required</strong> for KYAML (while it’s optional in YAML).</p>

<h2 class="relative group">Experimentation and Additional Observations
    <div id="experimentation-and-additional-observations" class="anchor"></div>
    
</h2>
<ul>
<li>I was initially excited about converting all my Kubernetes manifests to the “safer” KYAML format.</li>
<li>I ran my script then followed it by running <a href="https://github.com/adrienverge/yamllint"  target="_blank" rel="noreferrer"><code>yamllint</code></a>, which introduced a few warnings post-conversion.</li>
<li>After fixing all yamllint warnings, I had well-formatted KYAML files.</li>
<li>I considered whether to rename all converted manifest files to use a <code>*.kyaml</code> suffix. I decided against this since I couldn’t find any evidence of this file extension.</li>
<li>KYAML files are 100% valid YAML files, and work with existing tooling. This includes existing Kubernetes versions and tooling.</li>
<li>The main thing introduced with Kubernetes v1.34 is a <code>kubectl get -o kyaml</code> option.</li>
<li>Keeping the <code>*.yaml</code> file extension makes sense since KYAML is still valid YAML and existing tools expect <code>*.yaml</code> or <code>*.yml</code> file extensions, not <code>*.kyaml</code></li>
<li>After running the script, fixing formatting, and deciding to keep the filenames the same, I could add all modified files in <code>homelab-as-code</code> to a new <code>kyaml</code> branch and make a commit.</li>
<li>I considered opening a Pull Request, however, am still undecided.</li>
<li>My main consideration is whether the KYAML format would impact usability, making it harder for me to write and edit manifests.</li>
<li>I am not sure whether KYAML solves any real problems for me.</li>
<li>I understand YAML limitations but know how to avoid them by quoting values when needed, using linting and formatting tools (manually, with <a href="https://pre-commit.com/"  target="_blank" rel="noreferrer">pre-commit</a>and in CI).</li>
</ul>

<h2 class="relative group">My Opinion on the Format
    <div id="my-opinion-on-the-format" class="anchor"></div>
    
</h2>
<p>In a way, KYAML is itself “yet another markup language” (despite using existing YAML rules). It is far from the first solution to problems with existing markup languages.</p>
<p>One notable limitation of standarad JSON is no comments. Both <a href="https://json5.org/"  target="_blank" rel="noreferrer">JSON5</a> and Microsoft’s <a href="https://github.com/microsoft/node-jsonc-parser"  target="_blank" rel="noreferrer">JSONC</a> (JSON with comments, primarily used in VS Code’s <a href="https://code.visualstudio.com/docs/configure/settings#_settings-json-file"  target="_blank" rel="noreferrer">setttings.json</a> file) previously addressed this. KYAML has the benefit of being a <em>subset</em> of YAML and designed to work with all existing YAML tooling.</p>
<p>In theory, KYAML could be a “safer” way to write production-grade manifests. However, this was already possible to do with JSON files. Kubernetes manifests can all be written in JSON, but there is a reason that this is rarely done in practice.</p>
<p>JSON files are arguably less readable and harder to work with (for humans, not machines) than YAML. At the same time, JSON files are very much machine-parsable with a lot of existing tooling like <a href="https://jqlang.org/"  target="_blank" rel="noreferrer">jq</a> (though YAML tooling exists as well).</p>
<p>In imitating JSON but staying YAML, KYAML can feel like the worst of both, rather than the best of both world. Not as clean as JSON, and not as “human-readable” as YAML.</p>
<hr>
<p><em>Featured image by <a href="https://unsplash.com/@marvelous?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Marvin Meyer</a> on <a href="https://unsplash.com/?utm_source=hugo&utm_medium=referral"  target="_blank" rel="noreferrer">Unsplash</a>.</em></p>
]]></content><author><name>Ro'i Bandel</name></author><category term="kubernetes" label="Kubernetes" scheme="https://www.towerofkubes.com/tags/kubernetes/"/><category term="k8s" label="K8s" scheme="https://www.towerofkubes.com/tags/k8s/"/><category term="yaml" label="Yaml" scheme="https://www.towerofkubes.com/tags/yaml/"/><category term="tools" label="Tools" scheme="https://www.towerofkubes.com/tags/tools/"/><category term="til" label="Til" scheme="https://www.towerofkubes.com/tags/til/"/><published>2025-08-11T00:00:00Z</published></entry></feed>