<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Rancher Desktop Blog</title>
        <link>https://docs.rancherdesktop.io/blog/</link>
        <description>News and updates from the Rancher Desktop team</description>
        <lastBuildDate>Wed, 29 Jul 2026 09:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>Copyright © 2026 SUSE Rancher. All Rights Reserved.</copyright>
        <item>
            <title><![CDATA[Rancher Desktop 2.0 Alpha 2: the Preferences dialog is back]]></title>
            <link>https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/</link>
            <guid>https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/</guid>
            <pubDate>Wed, 29 Jul 2026 09:00:00 GMT</pubDate>
            <description><![CDATA[Alpha 1 of Rancher Desktop 2.0 shipped without a Preferences dialog. Everything worked, but you could only change settings from the command line. Alpha 2 brings the dialog back, and it reads and writes the same App object as the command line tools do.]]></description>
            <content:encoded><![CDATA[<p>Alpha 1 of Rancher Desktop 2.0 shipped without a Preferences dialog. Everything
worked, but you could only change settings from the command line. Alpha 2
brings the dialog back, and it reads and writes the same <code>App</code> object as the
command line tools do.</p>
<img class="blog-screenshot" src="https://suse-rancher-media.s3.amazonaws.com/desktop/blog/2026/rancher-desktop-2-alpha-2/preferences-kubernetes.png" alt="The Rancher Desktop 2.0 Preferences dialog on the Kubernetes tab, showing the Enable Kubernetes checkbox and the Kubernetes version dropdown. Diagonal stripes ring the selected tab.">
<p>The stripes behind the selected tab mark a pre-release build, and the app icon
wears the same pattern. Development builds of 2.0 get them too, and the stripes
will come off in the final 2.0.0 release.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-in-it">What's in it<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#whats-in-it" class="hash-link" aria-label="Direct link to What's in it" title="Direct link to What's in it" translate="no">​</a></h2>
<p>The dialog has three sections. <strong>Application</strong> turns automatic update checks on
or off. <strong>Virtual Machine</strong> sets how many CPUs and how much memory the VM gets.
<strong>Kubernetes</strong> enables the cluster and picks its version.</p>
<p>That's a short list next to Rancher Desktop 1.x. More settings will be
reintroduced as they are added to the <code>App</code> object and implemented by the
daemon.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="its-an-api-client">It's an API client<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#its-an-api-client" class="hash-link" aria-label="Direct link to It's an API client" title="Direct link to It's an API client" translate="no">​</a></h2>
<p>Two earlier posts explained that <code>rdd</code> is
<a class="" href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/">a Kubernetes API server</a>,
and that you can
<a class="" href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/">watch it reconcile</a> a change you
make with <code>rdd set</code>. The Preferences dialog is just another client of that same
API. Every control is bound to a field path on the <code>App</code> object, so applying
the changes you made in the dialog and running <code>rdd set</code> both update the same
field.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-the-controls-get-their-values">Where the controls get their values<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#where-the-controls-get-their-values" class="hash-link" aria-label="Direct link to Where the controls get their values" title="Direct link to Where the controls get their values" translate="no">​</a></h2>
<p>The dialog doesn't invent the choices it offers. The CPU and memory controls
get their limits from the daemon, which publishes them as a <code>HostInfo</code> object:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> ctl get hostinfo</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">NAME     CPUS   MEMORY</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">system   20     137438953472</span><br></div></code></pre></div></div>
<p>Those are the same numbers the daemon checks against, so asking for more than
the machine has gets you turned down:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash builtin class-name">set</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash assign-left variable" style="color:#36acaa">virtualMachine.cpus</span><span class="token command bash language-bash operator" style="color:#393A34">=</span><span class="token command bash language-bash number" style="color:#36acaa">192</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">ERRO[0000] failed to update App: admission webhook "app-validator.app.rancherdesktop.io" denied the request: spec.virtualMachine.cpus 192 exceeds the host CPU count of 20</span><br></div></code></pre></div></div>
<p>The Kubernetes dropdown comes from the same place. The daemon publishes the
versions it supports as a <code>k3s-versions</code> ConfigMap, and the dropdown is a view
of it. Versions that head a channel appear under <strong>Recommended Versions</strong>, the
rest under <strong>Other Versions</strong>. This build carries k3s 1.32 through 1.35.</p>
<p>You can read that one too:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> ctl get configmap k3s-versions </span><span class="token command bash language-bash parameter variable" style="color:#36acaa">--namespace</span><span class="token command bash language-bash"> rancher-desktop </span><span class="token command bash language-bash parameter variable" style="color:#36acaa">--output</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash assign-left variable" style="color:#36acaa">jsonpath</span><span class="token command bash language-bash operator" style="color:#393A34">=</span><span class="token command bash language-bash string" style="color:#e3116c">'{.data.channels}'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">{"1.32":"1.32.13","1.33":"1.33.10","1.34":"1.34.6","1.35":"1.35.3","latest":"1.35.3","stable":"1.34.6"}</span><br></div></code></pre></div></div>
<p>The channel aliases work from the command line:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> </span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">kubernetes.version</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">stable</span><br></div></code></pre></div></div>
<p><code>rdd set</code> exists so you don't have to write the JSON or know which kind of
patch to use. Underneath, this is the request it sends for you:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> ctl patch app app </span><span class="token parameter variable" style="color:#36acaa">--type</span><span class="token plain"> merge </span><span class="token parameter variable" style="color:#36acaa">--patch</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'{"spec":{"kubernetes":{"version":"stable"}}}'</span><br></div></code></pre></div></div>
<p>When you read the value back you can see that the alias has been replaced by
the defaulter<sup><a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#user-content-fn-webhook-1b2714" id="user-content-fnref-webhook-1b2714" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup> with the actual version before it was stored in the
object:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> ctl get app app </span><span class="token command bash language-bash parameter variable" style="color:#36acaa">--output</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash assign-left variable" style="color:#36acaa">jsonpath</span><span class="token command bash language-bash operator" style="color:#393A34">=</span><span class="token command bash language-bash string" style="color:#e3116c">'{.spec.kubernetes.version}'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">1.34.6</span><br></div></code></pre></div></div>
<p>There's no <code>rdd get</code> yet, so you have to use the generic <code>rdd ctl get</code>.</p>
<p>Right now a static k3s version list ships with the app. In the future
it will update itself at runtime, just like in Rancher Desktop 1.x.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-rest-of-alpha-2">The rest of Alpha 2<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#the-rest-of-alpha-2" class="hash-link" aria-label="Direct link to The rest of Alpha 2" title="Direct link to The rest of Alpha 2" translate="no">​</a></h2>
<p>The <a href="https://github.com/rancher-sandbox/rancher-desktop-2/releases/tag/v2.0.0-alpha.2" target="_blank" rel="noopener noreferrer" class="">release notes</a>
have the full list; here are three of the changes:</p>
<ol>
<li class="">On Linux, 2.0 finally installs beside 1.x. The RPM and DEB claimed the same
file names, so the two packages conflicted, and the launcher we shipped ran
the 1.x binary.</li>
<li class="">On Windows, the host-side network bridge moved into the per-VM host agent,
so its ports and listeners now go away with the VM instead of outliving it.</li>
<li class=""><code>~/.kube/config</code> is safe from overlapping writers, which could previously
tear it into invalid YAML or drop the clusters you use with other tools.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="still-an-alpha">Still an alpha<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#still-an-alpha" class="hash-link" aria-label="Direct link to Still an alpha" title="Direct link to Still an alpha" translate="no">​</a></h2>
<p>This is a preview. Expect rough edges, and don't put it in front of anything
you care about. There's no upgrade path between previews, and Alpha 2 refuses
to start against a backend Alpha 1 created. Clear the old one first:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> svc delete</span><br></div></code></pre></div></div>
<p>That takes the containers, images, volumes, and cluster with it. So there's
nothing to carry across. Then install Alpha 2. It sits alongside Rancher
Desktop 1.x without touching it, though only one of them can run at a time.</p>
<p>On Windows, the Virtual Machine tab shows the CPU and memory controls, but
WSL2 ignores them because the VM settings are global across all WSL2 distros.
You can change the defaults in <code>.wslconfig</code>.</p>
<p>Downloads and the full list of changes are in the
<a href="https://github.com/rancher-sandbox/rancher-desktop-2/releases/tag/v2.0.0-alpha.2" target="_blank" rel="noopener noreferrer" class="">release</a>,
and the <a class="" href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/">installation post</a> still covers
getting it running, GUI or backend-only.</p>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/620" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-webhook-1b2714">
<p>In Kubernetes terms it's a mutating admission webhook, which rewrites values on their way in, as opposed to a validating one that only answers yes or no. <a href="https://docs.rancherdesktop.io/blog/rancher-desktop-2-alpha-2/#user-content-fnref-webhook-1b2714" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
        <item>
            <title><![CDATA[Watching Rancher Desktop reconcile]]></title>
            <link>https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/</link>
            <guid>https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/</guid>
            <pubDate>Tue, 28 Jul 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[Rancher Desktop 2.0's settings screen covers a handful of fields, and the API underneath it has no reference docs. But you don't really need them; you can ask rdd itself what you can change, and once you change something, you can watch it reshape the virtual machine, step by step, until the actual state matches what you asked for.]]></description>
            <content:encoded><![CDATA[<p>Rancher Desktop 2.0's settings screen covers a handful of fields, and the API
underneath it has no reference docs. But you don't really need them; you can
ask <code>rdd</code> itself what you can change, and once you change something, you can
watch it reshape the virtual machine, step by step, until the actual state
matches what you asked for.</p>
<p>The <a class="" href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/">companion post</a> explains
why Rancher Desktop can behave this way. <code>rdd</code> is a Kubernetes API server, and
Rancher Desktop's own configuration lives in it as a single object called
<code>App</code>. This post is about what that buys you in practice.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-api-describes-itself">The API describes itself<a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#the-api-describes-itself" class="hash-link" aria-label="Direct link to The API describes itself" title="Direct link to The API describes itself" translate="no">​</a></h2>
<p>There are no external docs for the <code>App</code> object, but it doesn't need any,
because you can query the API itself for documentation. You can read it with
<code>explain</code>, for example:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> ctl explain app.spec.kubernetes</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">FIELD: kubernetes &lt;Object&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token output"></span><br></div><div class="token-line" style="color:#393A34"><span class="token output">DESCRIPTION:</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">    kubernetes specifies the Kubernetes configuration.</span><br></div><div class="token-line" style="color:#393A34"><span class="token output"></span><br></div><div class="token-line" style="color:#393A34"><span class="token output">FIELDS:</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  enabled   &lt;boolean&gt; -required-</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">    enabled specifies whether Kubernetes should be enabled in the VM.</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  version   &lt;string&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">    version is the Kubernetes version to use (e.g. "1.32.2").</span><br></div></code></pre></div></div>
<p>You can walk any part of the object, from <code>app.spec</code> down to a single field.
The descriptions are not baked into <code>explain</code>; they come straight from <a href="https://github.com/rancher-sandbox/rancher-desktop-2/blob/8810bada2a02d88f91391cc7d6c56f305239d04b/rdd/pkg/apis/app/v1alpha1/app_types.go#L164-L171" target="_blank" rel="noopener noreferrer" class="">the Go
source</a>.
Each field on the <code>App</code> type carries a comment, a build step turns those types
into the CRD<sup><a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#user-content-fn-crd-815470" id="user-content-fnref-crd-815470" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup> and copies the comments into its OpenAPI schema, and the API
server hands that schema to any client that asks (<code>explain</code> is just one such
client). So the documentation is generated from the code, and it cannot drift
out of sync with it.</p>
<p>The writable side works the same way. <code>rdd set</code> is how you change the <code>App</code>
object, and it says up front where its knobs come from: "Valid property names
and types are derived from the App CRD at runtime." So the property list in its
help comes straight from the CRD too:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash builtin class-name">set</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash parameter variable" style="color:#36acaa">--help</span><span class="token command bash language-bash">   </span><span class="token command bash language-bash comment" style="color:#999988;font-style:italic"># trimmed to the property list</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">Available properties:</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  containerEngine.name  (moby|containerd)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  kubernetes.enabled    (boolean)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  kubernetes.version    (string)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  running               (boolean)</span><br></div></code></pre></div></div>
<p>Each of those shows the same description you'd get from <code>explain</code>, and
nobody maintains this list by hand; when we add a field to the <code>App</code> type,
it turns up here, typed and documented, in the next build.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-setting-in-motion">One setting in motion<a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#one-setting-in-motion" class="hash-link" aria-label="Direct link to One setting in motion" title="Direct link to One setting in motion" translate="no">​</a></h2>
<p>So let's change something, and turn Kubernetes on:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> </span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">kubernetes.enabled</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">true</span><br></div></code></pre></div></div>
<p>The command doesn't return right away. It writes your one-line change into the
<code>App</code> object's <code>spec</code> and then waits, quietly, until everything has settled.
<code>rdd</code> logs at warn level by default, and a condition changing is only info, so
you see nothing unless you ask for it. Ask, and you can watch it work:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> --log-level</span><span class="token command bash language-bash operator" style="color:#393A34">=</span><span class="token command bash language-bash">info </span><span class="token command bash language-bash builtin class-name">set</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash assign-left variable" style="color:#36acaa">kubernetes.enabled</span><span class="token command bash language-bash operator" style="color:#393A34">=</span><span class="token command bash language-bash">true   </span><span class="token command bash language-bash comment" style="color:#999988;font-style:italic"># trimmed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">INFO[0000] App updated</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0000] Waiting for App to settle</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0000] ContainerEngineReady=True: Container engine synced (Connected)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0000] Settled=False: Applying the configuration change to the VM (ApplyingTemplate)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0000] ContainerEngineReady=False: failed to ping Docker: ... no such file or directory (ConnectFailed)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0002] Running=False: Stopped for restart (Stopped)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0002] Running=False: Lima instance is starting (Starting)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0002] ContainerEngineReady=False: Container engine stopped (Stopped)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0022] Running=True: Lima instance is running (Started)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0022] KubernetesReady=False: Waiting for k3s API server (Probing)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0022] ContainerEngineReady=True: Container engine synced (Connected)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0027] KubernetesReady=True: Kubernetes cluster is ready (Ready)</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">INFO[0027] Settled=True: App has reached the desired state (Settled)</span><br></div></code></pre></div></div>
<p>The whole change took 27 seconds,<sup><a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#user-content-fn-clock-815470" id="user-content-fnref-clock-815470" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">2</a></sup> and 20 of those were the VM
restarting. The Docker error partway through comes from that same restart.
The container engine goes down with the VM, so its socket disappears for a
while, and <code>ContainerEngineReady</code> goes from connected to failed to stopped and
back again. Conditions describe the state at that moment. They change as often
as the state does.</p>
<p>That's all ordinary Kubernetes behaviour. You wrote down a desired state. A
controller saw the gap between what you asked for and what was actually true,
and closed it. To do that, it reconfigured the virtual machine and
restarted it, waited for k3s to answer, and merged the new cluster into your
kubeconfig. Most of those lines are a condition changing on the <code>App</code> object's
<code>status</code>; these are the same conditions you'd watch on a Deployment rolling
out. <code>rdd set</code> returns once <code>Settled</code> reaches <code>True</code>. The cluster is up at that
point.</p>
<p>That's the reconcile loop, the pattern Kubernetes itself is built on. Rancher
Desktop manages a VM and a cluster the same way Kubernetes manages your pods;
the approach survives interruption. Kill <code>rdd</code> in the middle of a change, and
the next start should pick up from wherever the world actually is. A script
would have to remember which steps it had already run, because a crash loses
that record.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-build-it-this-way">Why build it this way<a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#why-build-it-this-way" class="hash-link" aria-label="Direct link to Why build it this way" title="Direct link to Why build it this way" translate="no">​</a></h2>
<p>Modelling the app as a controller puts everything it can do behind an API, and
Rancher Desktop's own GUI is just another client of it. Nothing is locked
inside the window. Anything you can do by clicking, you can do from a script,
with <code>kubectl</code> or with the standard Kubernetes client libraries, and our own
integration tests exercise the application the same way a GUI user would.</p>
<p>The API also describes itself, which is what <code>explain</code> was doing earlier. You
can find out what a field is for without hunting down a separate document that
has since gone stale, and so can an autonomous AI agent working on your behalf.</p>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/619" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-crd-815470">
<p>A CustomResourceDefinition, the way you teach a Kubernetes API server about a new kind of object. The build step that writes it from the Go types is controller-gen. <a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#user-content-fnref-crd-815470" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-clock-815470">
<p>The number in brackets is seconds since the command started. <a href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/#user-content-fnref-clock-815470" data-footnote-backref="" aria-label="Back to reference 2" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
        <item>
            <title><![CDATA[Rancher Desktop is a Kubernetes API server]]></title>
            <link>https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/</link>
            <guid>https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/</guid>
            <pubDate>Mon, 27 Jul 2026 09:00:00 GMT</pubDate>
            <description><![CDATA[Enable Kubernetes in Rancher Desktop 2.0 and you get a cluster, which is no surprise. But the daemon that runs it, rdd, is itself a Kubernetes API server too. It holds Rancher Desktop's own state as objects you can query. So there are actually two Kubernetes API servers on your machine, and only one of them runs your pods.]]></description>
            <content:encoded><![CDATA[<p>Enable Kubernetes in Rancher Desktop 2.0 and you get a cluster, which is no
surprise. But the daemon that runs it, <code>rdd</code>, is itself a Kubernetes API
server too. It holds Rancher Desktop's own state as objects you can query.
So there are actually two Kubernetes API servers on your machine, and only
one of them runs your pods.</p>
<p>Back in the <a class="" href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/">install walkthrough</a> I ran <code>rdd ctl get app</code>, watched Rancher Desktop's own state print as a Kubernetes object,
and said it deserved a post of its own, so here it is.</p>
<p><code>rdd</code>'s API server runs whether or not you ever enable Kubernetes, and it
stays up after you turn Kubernetes off again. That sounds odd, but it makes
sense once you know that Kubernetes really is two separate things sharing a
single name.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="kubernetes-is-two-things">Kubernetes is two things<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#kubernetes-is-two-things" class="hash-link" aria-label="Direct link to Kubernetes is two things" title="Direct link to Kubernetes is two things" translate="no">​</a></h2>
<p>The part everyone knows is the workload layer: the kubelet on each node, the
pods, and your containers. You hand it a Deployment, and it finds a node and
runs the thing. But the other part is the control plane, where an API server
holds resources and controllers reconcile them. You write down what you want;
the controllers work to make it true.</p>
<p>The control plane knows nothing about containers; it just stores objects and
runs reconcile loops. Containers are only created when the workload layer acts
on those objects.<sup><a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#user-content-fn-kubelet-2422cb" id="user-content-fnref-kubelet-2422cb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup> The control plane is a general engine for "here's
the state I want, go make it so." That engine is the part of Kubernetes <code>rdd</code>
uses for its own state and interface.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-app-object">The App object<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#the-app-object" class="hash-link" aria-label="Direct link to The App object" title="Direct link to The App object" translate="no">​</a></h2>
<p>Everything Rancher Desktop needs to know about itself lives in a single object
called <code>App</code>.<sup><a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#user-content-fn-singleton-2422cb" id="user-content-fnref-singleton-2422cb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">2</a></sup> You can ask for it the same way you'd ask any
cluster for a resource:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># rdd ctl get app app --output yaml   (trimmed)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> app.rancherdesktop.io/v1alpha1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> App</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> app</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">containerEngine</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> moby</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kubernetes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1.34.6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">running</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kubernetesPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7443</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">conditions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ContainerEngineReady</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Connected</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> KubernetesReady</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ready</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Settled</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Settled</span><br></div></code></pre></div></div>
<p>The <code>spec</code> is what you asked for: the moby engine, Kubernetes enabled at
version 1.34.6, and the VM running. The <code>status</code> is what <code>rdd</code> observed, so the
port it put the cluster on (7443) shows up there, along with a list of
conditions reporting how far along it got. You only ever edit the <code>spec</code>; the
controllers write the <code>status</code>. Every Kubernetes resource works this way,
from a pod to a deployment, and now Rancher Desktop itself does too.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-control-plane-with-nothing-to-run">A control plane with nothing to run<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#a-control-plane-with-nothing-to-run" class="hash-link" aria-label="Direct link to A control plane with nothing to run" title="Direct link to A control plane with nothing to run" translate="no">​</a></h2>
<p>Ask this API server what kinds of objects it holds, and the list is short:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> ctl api-resources   </span><span class="token command bash language-bash comment" style="color:#999988;font-style:italic"># trimmed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">NAME               APIVERSION                              KIND</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">configmaps         v1                                      ConfigMap</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">secrets            v1                                      Secret</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">apps               app.rancherdesktop.io/v1alpha1          App</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">limavms            lima.rancherdesktop.io/v1alpha1         LimaVM</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">containers         containers.rancherdesktop.io/v1alpha1   Container</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">images             containers.rancherdesktop.io/v1alpha1   Image</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">volumes            containers.rancherdesktop.io/v1alpha1   Volume</span><br></div></code></pre></div></div>
<p>The standard building blocks are there (ConfigMaps, Secrets), right next to
Rancher Desktop's own kinds. But the whole workload layer is missing, so there
are no pods and no nodes. The server hasn't even heard of a node:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">rdd</span><span class="token command bash language-bash"> ctl get nodes</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">error: the server doesn't have a resource type "nodes"</span><br></div></code></pre></div></div>
<p><code>rdd</code> runs no containers, so it needs no kubelet, no scheduler, and none of the
other machinery that ties Kubernetes to a Linux host. The control plane is just
storage and reconcile loops, which is why the same one runs natively on macOS,
Windows, and Linux.
The <a class="" href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/">history post</a> made the case for a single
backend on every platform. Dropping the workload layer is most of what makes
that possible.</p>
<p>It does still need somewhere to keep its objects. Kubernetes stores them in
etcd;<sup><a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#user-content-fn-etcd-2422cb" id="user-content-fnref-etcd-2422cb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">3</a></sup> <code>rdd</code> uses SQLite instead, which is the same mechanism k3s uses
so it can ship as a single binary.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="so-where-is-the-cluster">So where is the cluster?<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#so-where-is-the-cluster" class="hash-link" aria-label="Direct link to So where is the cluster?" title="Direct link to So where is the cluster?" translate="no">​</a></h2>
<p>You did start a cluster, and it's real; <code>rdd ctl get nodes</code> came up empty
because the cluster lives somewhere else. It runs inside the virtual machine,
as a separate Kubernetes with its own API server. Point <code>kubectl</code> at that one,
and the node is right there:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">kubectl</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash parameter variable" style="color:#36acaa">--context</span><span class="token command bash language-bash"> rancher-desktop-2 get nodes</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">NAME      STATUS   ROLES           AGE   VERSION</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">lima-rd   Ready    control-plane   44s   v1.34.6+k3s1</span><br></div></code></pre></div></div>
<p>The two API servers do different jobs. The one <code>rdd ctl</code> talks to is Rancher
Desktop describing itself; the one <code>kubectl</code> talks to is the k3s cluster where
your workloads run. And <code>rdd</code>'s API server manages the cluster's; setting
<code>spec.kubernetes.enabled: true</code> on the <code>App</code> object is how you tell the control
plane to start the k3s cluster. I suspect two API servers on one machine will
trip people up for a while, until reaching for the right one becomes automatic.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="your-tools-already-work">Your tools already work<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#your-tools-already-work" class="hash-link" aria-label="Direct link to Your tools already work" title="Direct link to Your tools already work" translate="no">​</a></h2>
<p>Because Rancher Desktop represents itself as Kubernetes objects, and serves
them from a real Kubernetes API server, everything that already speaks that API
can drive <code>rdd</code>. <code>rdd ctl</code> really is just <code>kubectl</code>, pointed at the control
plane. So <code>get</code>, <code>--output yaml</code>, <code>--output jsonpath</code>, label selectors, and
watches all work, because there's never been anything custom to support.</p>
<p>This is quite different from a custom application API. There's no <code>rdd</code> SDK to
import, and no private protocol to figure out.</p>
<p>That leaves the question of how the control plane turns a one-line change to
the <code>App</code> object into a running cluster, and how you find your way around this
API when there are no docs for it. I take both up in a
<a class="" href="https://docs.rancherdesktop.io/blog/watching-rancher-desktop-reconcile/">companion post</a>.</p>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/618" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-kubelet-2422cb">
<p>The kubelet is the part that implements a node. It registers the Node object with the API server and runs whatever pods get assigned to it, from pulling the images to mounting the volumes. <a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#user-content-fnref-kubelet-2422cb" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-singleton-2422cb">
<p>There's only ever one, it's cluster-scoped, and it must be named <code>app</code>. Hence <code>get app app</code>, the kind followed by the name. <a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#user-content-fnref-singleton-2422cb" data-footnote-backref="" aria-label="Back to reference 2" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-etcd-2422cb">
<p>The distributed key-value store a normal Kubernetes cluster keeps its objects in. The shim that swaps it for SQLite is kine, borrowed from k3s. <a href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/#user-content-fnref-etcd-2422cb" data-footnote-backref="" aria-label="Back to reference 3" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
        <item>
            <title><![CDATA[Running a Rancher Desktop Development Build]]></title>
            <link>https://docs.rancherdesktop.io/blog/installing-development-builds/</link>
            <guid>https://docs.rancherdesktop.io/blog/installing-development-builds/</guid>
            <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[You reported a bug against Rancher Desktop, someone fixed it, and the issue got closed. But the fix is sitting on the main branch, and the next release is still weeks out. You'd rather know now, while reopening the issue is still easy. You can, because every merge to main, and every pull request, produces an installable Rancher Desktop build, whether you're on 1.x or 2.0. Running one is more involved than installing a release, and a bad build can damage files on your host.]]></description>
            <content:encoded><![CDATA[<p>You reported a bug against Rancher Desktop, someone fixed it, and the issue got
closed. But the fix is sitting on <code>main</code>, and the next release is still weeks
out. You'd rather know now, while reopening the issue is still easy.
You can, because every merge to <code>main</code>, and every pull request, produces an
installable Rancher Desktop build, whether you're on 1.x or 2.0. Running one is
more involved than installing a release, and a bad build can damage files on
your host.</p>
<p>Sometimes the fix or feature you want hasn't been merged to <code>main</code><sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-main-19acf8" id="user-content-fnref-main-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup> yet and
lives only in an open pull request<sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-pr-19acf8" id="user-content-fnref-pr-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">2</a></sup>. You can install that build too, and try
the change before it lands.</p>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_BuS1"><p>A development build hasn't been through the testing a release gets, so it can
break in ways nothing has caught yet. A bad one can damage files on your host,
outside the VM. Back up anything you can't afford to lose before you start.</p></div></div>
<p>So this is really for people who are comfortable switching between versions and
running factory resets, and who can put things back when a build breaks
something. If that's not you, I'd wait for the release; the fix will land there
soon enough.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-short-version">The short version<a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#the-short-version" class="hash-link" aria-label="Direct link to The short version" title="Direct link to The short version" translate="no">​</a></h2>
<p><strong>On Rancher Desktop 1.x</strong></p>
<ol>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#have-a-way-back-before-you-start" class="">Take a snapshot</a> first.</li>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#find-the-build" class="">Find the build</a> and download the artifact for your machine.</li>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#unpack-and-install" class="">Unpack and install it</a>. On macOS, clear the quarantine
flag, or it refuses to open.</li>
<li class="">Check whether it fixes your problem, or try the feature you wanted.</li>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#going-back-to-a-release" class="">Factory-reset</a> from the development build.</li>
<li class="">Install the release by hand, then restore the snapshot from step 1.</li>
</ol>
<p><strong>On Rancher Desktop 2.0</strong></p>
<ol>
<li class="">There's no snapshot to take, so your existing workloads are gone either way.</li>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#find-the-build" class="">Find the build</a> and download the artifact for your machine.</li>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#unpack-and-install" class="">Unpack and install it</a>. On macOS, clear the quarantine
flag, or it refuses to open.</li>
<li class="">Clear the existing backend with <code>rdd svc delete</code> before you start.</li>
<li class="">Check whether it fixes your problem, or try the feature you wanted.</li>
<li class=""><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#going-back-to-a-release" class="">Clear the backend again</a> with <code>rdd svc delete</code>,
then install the release by hand.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="have-a-way-back-before-you-start">Have a way back before you start<a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#have-a-way-back-before-you-start" class="hash-link" aria-label="Direct link to Have a way back before you start" title="Direct link to Have a way back before you start" translate="no">​</a></h2>
<p>There's no in-place downgrade back to a release. Going back takes a factory reset,
and that reset wipes everything the backend is holding: your containers, images,
volumes, and Kubernetes cluster.</p>
<p>So on Rancher Desktop 1.x, take a snapshot before you install the development
build. It captures all of that, and you can restore it once you're back on a
release. Rancher Desktop 2.0 has no snapshot mechanism yet. It also refuses to
start on a backend that a different <code>rdd</code><sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-rdd-19acf8" id="user-content-fnref-rdd-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">3</a></sup> version created; switching
versions there means clearing the backend and losing those workloads, in either
direction. And even where you can snapshot, it only covers what's in the VM. A
snapshot is not a backup of your host, and it won't save you from a build that
damages files there.</p>
<p>A development build also turns off auto-updates. It won't quietly replace itself,
and it won't pull you back onto a release either. You reinstall the release build
by hand when you're done.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="find-the-build">Find the build<a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#find-the-build" class="hash-link" aria-label="Direct link to Find the build" title="Direct link to Find the build" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>Before you start</div><div class="admonitionContent_BuS1"><p>You need a GitHub account, and you have to be signed in before GitHub will let
you download a build.</p><p>Everything below happens in one of two repositories,
<a href="https://github.com/rancher-sandbox/rancher-desktop" target="_blank" rel="noopener noreferrer" class="">rancher-sandbox/rancher-desktop</a>
for 1.x or
<a href="https://github.com/rancher-sandbox/rancher-desktop-2" target="_blank" rel="noopener noreferrer" class="">rancher-sandbox/rancher-desktop-2</a>
for 2.0.</p></div></div>
<p>Development builds come from GitHub Actions<sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-actions-19acf8" id="user-content-fnref-actions-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">4</a></sup>, from the workflow named
<strong>Package</strong>.</p>
<p>For the latest <code>main</code>, open the <strong>Actions</strong> tab, then filter to the <strong>Package</strong>
workflow and the <code>main</code> branch. Or skip both dropdowns and type
<code>branch:main workflow:Package</code> into the search box. Now pick the newest run with
a green checkmark, which means the whole run passed and its builds are complete.</p>
<img class="blog-screenshot" src="https://suse-rancher-media.s3.amazonaws.com/desktop/blog/2026/installing-development-builds/actions-package-main.png" alt="The GitHub Actions tab, filtered to the Package workflow on the main branch, with the newest successful run at the top of the list.">
<p>For a pull request, open the PR and scroll down to its checks. Expand them,
find a green check whose name starts with <code>Package / package</code>, and click it. The
platform in the parentheses doesn't matter. They all belong to the same run;
any of them gets you there.</p>
<img class="blog-screenshot" src="https://suse-rancher-media.s3.amazonaws.com/desktop/blog/2026/installing-development-builds/pr-checks-package.png" alt="An open pull request with its checks expanded, showing a green Package / package check for each platform.">
<p>Either way, you land on a workflow run. Click <strong>Summary</strong> in the left sidebar,
then scroll to the bottom, where GitHub lists the artifacts. Each artifact is one
operating system and CPU architecture. Find the one for your machine and click the
download icon beside it. They're large, 600 MB and up.</p>
<img class="blog-screenshot" src="https://suse-rancher-media.s3.amazonaws.com/desktop/blog/2026/installing-development-builds/run-summary-artifacts.png" alt="A workflow run Summary page with the Artifacts list, showing the installer, disk image, and zip downloads for each platform.">
<p>On 2.0, the same run also produces an <code>RDD</code> artifact for each platform, which
holds just the <code>rdd</code> binary with no app and no bundled tools. For testing a
backend fix you could use just this binary, as it's 50 to 60 MB (rather than
600 plus), but GUI changes would still require downloading the full app. The
binary still needs its quarantine flag cleared on macOS. The
<a class="" href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/">installation post</a> covers using <code>rdd</code> on its
own.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="unpack-and-install">Unpack and install<a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#unpack-and-install" class="hash-link" aria-label="Direct link to Unpack and install" title="Direct link to Unpack and install" translate="no">​</a></h2>
<p>What you downloaded is a ZIP, even on macOS and Windows, where a release hands
you a <code>.dmg</code> or an installer directly. GitHub wraps every build artifact in a ZIP
of its own. On every platform you unzip what you got first; the real artifact is
inside.</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-console codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token command shell-symbol important">$</span><span class="token command"> </span><span class="token command bash language-bash function" style="color:#d73a49">unzip</span><span class="token command bash language-bash"> </span><span class="token command bash language-bash string" style="color:#e3116c">"Rancher Desktop.aarch64.dmg.zip"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token output">Archive:  Rancher Desktop.aarch64.dmg.zip</span><br></div><div class="token-line" style="color:#393A34"><span class="token output">  inflating: Rancher Desktop-1.23.1-300-ge397ee701-arm64.dmg</span><br></div></code></pre></div></div>
<p>The name changes on the way out<sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-arch-19acf8" id="user-content-fnref-arch-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">5</a></sup>. That <code>1.23.1-300-ge397ee701</code> is
<code>git describe</code> output, which pins down which build you ran<sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-msi-19acf8" id="user-content-fnref-msi-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">6</a></sup>. Don't go
hunting for that commit though. On a pull request GitHub builds a throwaway
merge of the branch into its base, so it only exists for that run. Link the run
itself when you report back.</p>
<p>On <strong>macOS</strong>, that inner artifact is a <code>.dmg</code> (pick the one matching your chip,
<code>aarch64</code> for Apple silicon or <code>x86_64</code> for Intel). Open it and drag the app into
Applications, the same as a release. Because the build is unsigned, macOS marks it
as quarantined and refuses to open it, so clear that flag once from a terminal.
The 1.x app is <code>Rancher Desktop</code>; the 2.0 app is <code>Rancher Desktop 2</code>. Use the
one you installed:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">xattr </span><span class="token parameter variable" style="color:#36acaa">-rd</span><span class="token plain"> com.apple.quarantine </span><span class="token string" style="color:#e3116c">"/Applications/Rancher Desktop.app"</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic"># 1.x</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">xattr </span><span class="token parameter variable" style="color:#36acaa">-rd</span><span class="token plain"> com.apple.quarantine </span><span class="token string" style="color:#e3116c">"/Applications/Rancher Desktop 2.app"</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># 2.0</span><br></div></code></pre></div></div>
<p>On <strong>Windows</strong>, the inner artifact is an <code>.msi</code> installer. Run it. Windows will
warn that it comes from an unknown publisher, again because the build is
unsigned; approve it to continue.</p>
<p>On <strong>Linux</strong>, the development build extracts to <code>/opt/rancher-desktop</code>, the same
place our RPM and DEB packages install to. So if you have Rancher Desktop from one
of those repositories, remove the package first; otherwise the two fight over
that directory. If you extracted a development build there before, clear it out with
<code>sudo rm -rf /opt/rancher-desktop</code>.</p>
<p>The download itself holds a second ZIP with the application. Unpack that inner ZIP
into place, then make the sandbox helper setuid so the app can launch:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">unzip</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Rancher Desktop-linux.zip"</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># yields rancher-desktop-&lt;version&gt;-linux.zip</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">unzip</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> rancher-desktop-*-linux.zip </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> /opt/rancher-desktop</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> 04755 /opt/rancher-desktop/chrome-sandbox</span><br></div></code></pre></div></div>
<p>A manual extract leaves no desktop entry behind. Launch it directly with
<code>/opt/rancher-desktop/rancher-desktop</code><sup><a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fn-linux-exe-19acf8" id="user-content-fnref-linux-exe-19acf8" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">7</a></sup>.</p>
<p>On Rancher Desktop 2.0, the app refuses to start on a backend that a different
<code>rdd</code> version created. You have to clear any existing one first (this removes
your current 2.0 workloads). The command is the same on every platform:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> svc delete</span><br></div></code></pre></div></div>
<p>Then start Rancher Desktop the way you normally would; it runs like any release.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="going-back-to-a-release">Going back to a release<a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#going-back-to-a-release" class="hash-link" aria-label="Direct link to Going back to a release" title="Direct link to Going back to a release" translate="no">​</a></h2>
<p>Once you're finished with the development build, clear its backend so a release
can start clean. On Rancher Desktop 1.x that's <code>rdctl factory-reset</code>; on 2.0 it's
<code>rdd svc delete</code>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdctl</span><span class="token plain"> factory-reset   </span><span class="token comment" style="color:#999988;font-style:italic"># Rancher Desktop 1.x</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> svc delete        </span><span class="token comment" style="color:#999988;font-style:italic"># Rancher Desktop 2.0</span><br></div></code></pre></div></div>
<p>Then install the release the normal way, from the project's releases page, or on
Linux from our package repositories. On Rancher Desktop 1.x, restore the snapshot
you took at the start, and your containers and cluster come back as they were. On
2.0 there's no snapshot to restore; you start fresh.</p>
<p>It's a lot of steps, though it does answer "is this actually fixed?" weeks ahead
of the release.</p>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/575" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-main-19acf8">
<p><code>main</code> is the primary line of development in the project's git repository on GitHub. A fix lands there once it is accepted, ahead of the next release. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-main-19acf8" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-pr-19acf8">
<p>A pull request proposes a change and holds it for review until it is merged. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-pr-19acf8" data-footnote-backref="" aria-label="Back to reference 2" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-rdd-19acf8">
<p><code>rdd</code>, the Rancher Desktop Daemon, is the background program that runs the VM, the container engine, and the cluster in 2.0. <a class="" href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/">Welcome to Rancher Desktop 2.0</a>. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-rdd-19acf8" data-footnote-backref="" aria-label="Back to reference 3" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-actions-19acf8">
<p>GitHub Actions is GitHub's build service. Each time a workflow runs it can leave files behind, called artifacts, which stay available for download. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-actions-19acf8" data-footnote-backref="" aria-label="Back to reference 4" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-arch-19acf8">
<p>The artifact says <code>aarch64</code>, but the file inside says <code>arm64</code>. The <code>x86_64</code> build carries no architecture in its name at all. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-arch-19acf8" data-footnote-backref="" aria-label="Back to reference 5" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-msi-19acf8">
<p>The 2.0 Windows installer is the exception, named <code>Rancher.Desktop.Setup.2.0.0.msi</code> with no build information in it. <a href="https://github.com/rancher-sandbox/rancher-desktop-2/issues/572" target="_blank" rel="noopener noreferrer" class="">Issue #572</a>. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-msi-19acf8" data-footnote-backref="" aria-label="Back to reference 6" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-linux-exe-19acf8">
<p>2.0 uses the same path and executable name as 1.x, which is why the two collide on Linux. That may change in alpha 2. <a href="https://github.com/rancher-sandbox/rancher-desktop-2/issues/509" target="_blank" rel="noopener noreferrer" class="">Issue #509</a>. <a href="https://docs.rancherdesktop.io/blog/installing-development-builds/#user-content-fnref-linux-exe-19acf8" data-footnote-backref="" aria-label="Back to reference 7" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
        <item>
            <title><![CDATA[Welcome to Rancher Desktop 2.0]]></title>
            <link>https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/</link>
            <guid>https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/</guid>
            <pubDate>Fri, 19 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Rancher Desktop 2.0 is a full rewrite, and the first build is ready for you]]></description>
            <content:encoded><![CDATA[<p>Rancher Desktop 2.0 is a full rewrite, and the first build is ready for you
to try. There's an alpha you can download today and run on your own machine.</p>
<p>Let's call it what it is: an early tech preview. It's rough, and not meant for
production. It exists so you can see that 2.0 is real and already running, and
so you can tell us what you'd like while the architecture is still soft
enough to change.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-20-is">What 2.0 is<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#what-20-is" class="hash-link" aria-label="Direct link to What 2.0 is" title="Direct link to What 2.0 is" translate="no">​</a></h2>
<p>We rewrote Rancher Desktop because the old design made every new feature take
more effort than the one before it. The <a class="" href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/">history
post</a> tells that story; the short version is
one backend instead of two, the engine lifted out of the GUI, and a different
guest OS underneath. 2.0 is that idea, built from scratch.</p>
<p>At the center is a new background program called <code>rdd</code>, the Rancher Desktop
Daemon, and it's the part that does the real work. It runs the virtual machine
(using Lima on all platforms now, including Windows), it starts your container
engine, and it manages your Kubernetes cluster. <code>rdd</code> exposes all of this
through an API, but not a custom one; it actually speaks the Kubernetes API, so
you can talk to it directly with <code>kubectl</code> or any of the standard client
libraries, and there's no new SDK to learn. The desktop app is really just
another client without any special privileges; it talks to <code>rdd</code> the same way
any other tool would.</p>
<p>Because the work lives in <code>rdd</code> instead of inside a window, you can run the
whole thing without ever opening the GUI. And <code>rdd</code> is one self-contained
executable; there's no installer and no separate daemon and command-line tool,
just one file that is both the backend and the way you drive it. Download it,
start it from the command line, and you have a container engine and a cluster:
on a headless server, on a CI runner, or in your own terminal. Deploying it
just means copying one file. Rancher Desktop never had a way to do this,
because the engine lived inside the app, and the app had to be on screen.</p>
<p>The guest VM runs openSUSE Leap now instead of Alpine, and the reason is glibc;
much of the GPU and AI tooling people ask for needs it, and Alpine's musl
doesn't provide it. GPU support isn't built yet, but the guest OS no longer
rules it out.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-an-alpha-and-why-now">Why an alpha, and why now<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#why-an-alpha-and-why-now" class="hash-link" aria-label="Direct link to Why an alpha, and why now" title="Direct link to Why an alpha, and why now" translate="no">​</a></h2>
<p>We could have kept this private until it looked polished, but we'd rather
not. Putting it out now, rough edges and all, does two things for us.</p>
<p>It shows that "we'll do that in 2.0" means a workstream already running, not a
promise about some distant year. And it puts the design in front of you early,
when your feedback still counts. If your setup depends on something specific,
this is the moment to say so, before we lock in decisions.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-can-do-today">What you can do today<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#what-you-can-do-today" class="hash-link" aria-label="Direct link to What you can do today" title="Direct link to What you can do today" translate="no">​</a></h2>
<p>This is a working preview, not a finished product. Here's what runs right now:</p>
<ul>
<li class="">Start, stop, and delete Rancher Desktop 2.0, from the GUI or the command line.</li>
<li class="">Install and run it with no GUI at all: the daemon with your local
command-line tools.</li>
<li class="">Build and run containers with the Docker (moby) engine.</li>
<li class="">Manage containers from the dashboard: start, stop, pause, resume, delete.</li>
<li class="">Turn on Kubernetes (version 1.31 or newer), switch versions, and browse the
cluster in the built-in dashboard.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-not-there-yet">What is not there yet<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#what-is-not-there-yet" class="hash-link" aria-label="Direct link to What is not there yet" title="Direct link to What is not there yet" translate="no">​</a></h2>
<p>So you're not caught off guard:</p>
<ul>
<li class="">moby is the only container engine for now.</li>
<li class="">There's no settings screen. You pick your Kubernetes version from the command
line.</li>
<li class="">So far, the interface covers containers, images, and volumes, plus the
cluster dashboard.</li>
<li class="">There's no upgrade path between previews. Each new build means a clean slate:
factory reset, then install fresh. It stays that way until 2.0 reaches a real
release.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="it-can-be-installed-beside-rancher-desktop-1x">It can be installed beside Rancher Desktop 1.x<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#it-can-be-installed-beside-rancher-desktop-1x" class="hash-link" aria-label="Direct link to It can be installed beside Rancher Desktop 1.x" title="Direct link to It can be installed beside Rancher Desktop 1.x" translate="no">​</a></h2>
<p>You don't have to choose. 2.0 installs next to Rancher Desktop 1.x, and the
two ignore each other, with a separate package and separate data. Install or
remove them in either order. The Linux RPM and DEB packages are the exception
in this alpha.<sup><a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#user-content-fn-linux-b38edc" id="user-content-fnref-linux-b38edc" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup> Don't run them both at once, though; there are likely to
be port and socket conflicts.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-try-it">How to try it<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#how-to-try-it" class="hash-link" aria-label="Direct link to How to try it" title="Direct link to How to try it" translate="no">​</a></h2>
<p>The full app, GUI plus bundled tools, comes from the <a href="https://github.com/rancher-sandbox/rancher-desktop-2/releases/latest" target="_blank" rel="noopener noreferrer" class="">latest
release</a>
on GitHub for Windows and macOS (Intel and Apple silicon), and from our RPM and
DEB repositories and AppImages on Linux, the same places you'd reach for
Rancher Desktop 1.x. If all you want is the daemon, download the single <code>rdd</code>
binary for your platform and you're two commands away from a running
container.</p>
<p>A real <a class="" href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/">installation and usage
walkthrough</a> is a separate post in this
series.</p>
<p>This is alpha software. Things will break, especially in corners we've never
tested on a machine configured like yours. When they do, please tell us; that
feedback is a big part of why we're shipping this early.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="staying-in-the-loop">Staying in the loop<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#staying-in-the-loop" class="hash-link" aria-label="Direct link to Staying in the loop" title="Direct link to Staying in the loop" translate="no">​</a></h2>
<p>There are no docs for 2.0 yet, so for now this blog takes their place. As the
work moves, we'll write about how the pieces fit and what becomes newly
possible: the daemon and its API, networking, snapshots, the AI story, whatever
we just released. To find out when the next preview drops, subscribe to the
feed.</p>
<p>Curious, and feeling adventurous? Give it a try. Cautious? Follow along, and
jump in when it looks ready for you.</p>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/473" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-linux-b38edc">
<p>The RPM and DEB packages share files with the Rancher Desktop 1.x package, such as <code>/usr/bin/rancher-desktop</code>, so the two will not install together. Use the AppImage to run 2.0 alongside 1.x. <a href="https://github.com/rancher-sandbox/rancher-desktop-2/issues/509" target="_blank" rel="noopener noreferrer" class="">Issue #509</a>. <a href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/#user-content-fnref-linux-b38edc" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
        <item>
            <title><![CDATA[Installing and Running Rancher Desktop 2.0]]></title>
            <link>https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/</link>
            <guid>https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/</guid>
            <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The 2.0 alpha is out, and there are two ways to run it. You can install the]]></description>
            <content:encoded><![CDATA[<p>The 2.0 alpha is out, and there are two ways to run it. You can install the
full desktop app, or you can skip the GUI and run the new <code>rdd</code> binary straight
from your terminal. Both leave Rancher Desktop 1.x alone, and both put you a
couple of commands away from a working container engine.</p>
<p>2.0 installs beside Rancher Desktop 1.x without touching it, with a
separate package and separate data. Install or remove them in any order. (The
<a class="" href="https://docs.rancherdesktop.io/blog/welcome-to-rancher-desktop-2/">welcome post</a> covers what 2.0 is and how
it differs; this one is about getting it running.)</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="install-the-desktop-app">Install the desktop app<a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#install-the-desktop-app" class="hash-link" aria-label="Direct link to Install the desktop app" title="Direct link to Install the desktop app" translate="no">​</a></h2>
<p>The full app, including the GUI and a set of bundled command-line tools, comes
from the
<a href="https://github.com/rancher-sandbox/rancher-desktop-2/releases/latest" target="_blank" rel="noopener noreferrer" class="">latest release</a>
on GitHub; its notes list the download for every platform. Open the <strong>Assets</strong>
list there.</p>
<p>On macOS, download the <code>.dmg</code> that matches your chip<sup><a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#user-content-fn-version-e85bc4" id="user-content-fnref-version-e85bc4" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup>:
<code>Rancher.Desktop-2.0.0-alpha.1.aarch64.dmg</code> on Apple silicon, or the <code>x86_64</code>
build on an Intel Mac. Open it, drag the app into Applications, and launch it
from there.</p>
<p>On Windows, download the installer, <code>Rancher.Desktop.Setup.2.0.0-alpha.1.msi</code>,
and run it. Install WSL2 first if you haven't already; 2.0 runs its Linux VM
through WSL2, just as Rancher Desktop 1.x does.</p>
<p>On Linux, install from our RPM or DEB repositories<sup><a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#user-content-fn-linux-e85bc4" id="user-content-fnref-linux-e85bc4" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">2</a></sup>, or run the AppImage,
similar to the channels used for Rancher Desktop 1.x.</p>
<p>The first time you launch the app, it sets up the backend and downloads the
VM image, which can take a while on a slow connection. After that the app is
talking to a running container engine, and you can manage containers, images,
and volumes from its window.</p>
<p>One thing the app won't do for you: turn on Kubernetes. It starts with
Kubernetes off. Turn it on from the Kubernetes section of Preferences, or from
the command line. The first run installs <code>rdd</code> into <code>~/.rd2/bin</code>; put that on
your <code>PATH</code> (or call <code>~/.rd2/bin/rdd</code> directly) and run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> </span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">kubernetes.enabled</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">true</span><br></div></code></pre></div></div>
<p>The VM is already running without Kubernetes, so this restarts it once.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="or-just-the-daemon">Or just the daemon<a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#or-just-the-daemon" class="hash-link" aria-label="Direct link to Or just the daemon" title="Direct link to Or just the daemon" translate="no">​</a></h2>
<p>If you want a container engine and a cluster with no window on screen, skip the
app and download the single <code>rdd</code> binary instead. It's the whole backend in
one file; there's no installer and nothing to unpack.</p>
<p>The binaries are in the same GitHub release. The name is <code>rdd-</code> followed by the
version, the operating system, and the CPU architecture: on an Apple silicon
Mac you want <code>rdd-2.0.0-alpha.1.darwin.aarch64</code>; on x86_64 Linux,
<code>rdd-2.0.0-alpha.1.linux.x86_64</code>. Download the one for your machine, put it on
your <code>PATH</code>, and make it executable:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--location</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--output</span><span class="token plain"> /usr/local/bin/rdd </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  https://github.com/rancher-sandbox/rancher-desktop-2/releases/download/v2.0.0-alpha.1/rdd-2.0.0-alpha.1.darwin.aarch64</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> +x /usr/local/bin/rdd</span><br></div></code></pre></div></div>
<p>From there, one command gets you a running container:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">--rm</span><span class="token plain"> hello-world</span><br></div></code></pre></div></div>
<p><code>rdd run</code> is the no-commitment way to use 2.0. It starts the daemon if it's
not already up, then runs your command with the <code>PATH</code> and the Docker and
Kubernetes contexts pointed at 2.0 for that command only. It leaves your own
configuration untouched. So if your machine is already set up for Rancher
Desktop 1.x, leave it that way and reach for 2.0 with <code>rdd run</code> when you want
to try something. The very first start downloads the openSUSE Leap image and
brings the VM up, which can take a while on a slow connection; after that it's
quick.</p>
<p>Kubernetes works the same way. On a fresh setup, <code>rdd run kubectl get node</code>
enables Kubernetes at the default version and runs against the new cluster,
with no separate step to turn it on:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> run </span><span class="token function" style="color:#d73a49">kubectl</span><span class="token plain"> get </span><span class="token function" style="color:#d73a49">node</span><br></div></code></pre></div></div>
<p>That shortcut fires only the first time, while nothing is configured yet. Once
Rancher Desktop exists, turn Kubernetes on with <code>rdd set</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> </span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">kubernetes.enabled</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">true</span><br></div></code></pre></div></div>
<p>The version defaults to the latest stable; pass <code>kubernetes.version=1.32.2</code> to
pin a specific one (1.32 through 1.35).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="driving-it">Driving it<a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#driving-it" class="hash-link" aria-label="Direct link to Driving it" title="Direct link to Driving it" translate="no">​</a></h2>
<p>The same <code>rdd</code> commands drive 2.0 whether you installed the full app or only the
binary. The GUI is an additional client; underneath, it runs the same daemon
as you do.</p>
<p><code>rdd run</code> is fine for the occasional command. If you use 2.0 a lot, add
<code>~/.rd2/bin</code> to your <code>PATH</code> and call the tools directly. The first start
populates that directory; add it to your <code>PATH</code> yourself, in this shell and in
your profile:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable environment constant" style="color:#36acaa">PATH</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string environment constant" style="color:#36acaa">$HOME</span><span class="token string" style="color:#e3116c">/.rd2/bin:</span><span class="token string environment constant" style="color:#36acaa">$PATH</span><span class="token string" style="color:#e3116c">"</span><br></div></code></pre></div></div>
<p>What you find there depends on how you installed. <code>rdd</code> provides <code>kubectl</code>
itself, so it's there either way. <code>docker</code> and <code>helm</code> come with the full app,
which links them into <code>~/.rd2/bin</code> alongside its other bundled tools and the
credential helpers; with the daemon-only download, supply <code>docker</code> and <code>helm</code>
yourself.</p>
<p>Both the Docker and Kubernetes contexts are
named <code>rancher-desktop-2</code>, and 2.0 won't take over a context you already
have selected. If you run both side by side, move between them by switching
contexts:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> context use rancher-desktop-2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">kubectl</span><span class="token plain"> config use-context rancher-desktop-2</span><br></div></code></pre></div></div>
<p>You don't need <code>rdd run</code> to manage the backend itself; <code>rdd start</code> brings it up
and <code>rdd stop</code> takes it down, keeping your data for next time:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> start   </span><span class="token comment" style="color:#999988;font-style:italic"># bring the backend up</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rdd</span><span class="token plain"> stop    </span><span class="token comment" style="color:#999988;font-style:italic"># take it down, keep your data</span><br></div></code></pre></div></div>
<p>There's no upgrade path between previews yet, so each new alpha starts from a
clean slate. <code>rdd svc delete</code> stops the daemon and removes everything 2.0
created (the VM, the cluster, your settings, and the daemon's own data),
keeping only the download cache so a reinstall doesn't refetch the VM image.
It's also how you uninstall; after it runs, just delete the <code>rdd</code> binary or
remove the app. The cache it leaves behind is Lima's, not ours
(<code>~/Library/Caches/lima</code> on macOS, <code>~/.cache/lima</code> on Linux,
<code>~/AppData/Local/lima</code> on Windows); delete it too if you want to reclaim all
the space. A later release will handle that for you, clearing distro images
from earlier previews automatically and adding a command to empty the cache.</p>
<p>That's the alpha: install it one of two ways, start it, and run a container.
It may break on setups we've never seen, and if it does, please tell us.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-glimpse-underneath">A glimpse underneath<a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#a-glimpse-underneath" class="hash-link" aria-label="Direct link to A glimpse underneath" title="Direct link to A glimpse underneath" translate="no">​</a></h2>
<p><code>rdd</code> is a Kubernetes API server in its own right, and Rancher Desktop's own
state lives inside it as Kubernetes objects. <code>rdd ctl</code> is <code>kubectl</code> aimed at that
API. Ask it for the App object and the whole machine prints as YAML: the
container engine, the requested Kubernetes version, and the conditions
tracking its progress toward the state you asked for.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># rdd ctl get app -o yaml</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">items</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> app.rancherdesktop.io/v1alpha1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> App</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-06-17T17:44:58Z"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">finalizers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> rdd.rancherdesktop.io/cleanup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">generation</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> app</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">resourceVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"507"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">uid</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 3ab44aec</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">8949</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">41b8</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">8432</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">03224fe38ce5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">containerEngine</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> moby</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kubernetes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1.34.6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">namespace</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> rancher</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">desktop</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">running</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">conditions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">lastTransitionTime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-06-19T00:57:05Z"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">message</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Container engine synced</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">observedGeneration</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Connected</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ContainerEngineReady</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">lastTransitionTime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-06-19T00:57:10Z"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">message</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Kubernetes cluster is ready</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">observedGeneration</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ready</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> KubernetesReady</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">lastTransitionTime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-06-17T17:45:19Z"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">message</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Lima instance created successfully</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">observedGeneration</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Created</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Created</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">lastTransitionTime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-06-19T00:57:10Z"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">message</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> App has reached the desired state</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">observedGeneration</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Settled</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Settled</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">lastTransitionTime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2026-06-19T00:57:05Z"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">message</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Lima instance is running</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">observedGeneration</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">reason</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Started</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"True"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Running</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kubernetesPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7443</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> List</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">resourceVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><br></div></code></pre></div></div>
<p>This is not the cluster you turned on earlier; it's Rancher Desktop
representing itself through the same API your tools already speak. That means
anything that drives Kubernetes can also drive Rancher Desktop, without a
bespoke SDK or a private protocol. There's a lot to say about that, and it has
<a class="" href="https://docs.rancherdesktop.io/blog/rancher-desktop-is-a-kubernetes-api-server/">a post of its own</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-commands-in-one-place">The commands in one place<a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#the-commands-in-one-place" class="hash-link" aria-label="Direct link to The commands in one place" title="Direct link to The commands in one place" translate="no">​</a></h2>
<div class="command-reference"><table><thead><tr><th>Command</th><th>What it does</th></tr></thead><tbody><tr><td><code>rdd run &lt;cmd&gt;</code></td><td>Run one command against 2.0, starting the daemon if needed and leaving your own setup untouched</td></tr><tr><td><code>rdd start</code></td><td>Bring the backend up</td></tr><tr><td><code>rdd stop</code></td><td>Take the backend down, keeping your data</td></tr><tr><td><code>rdd set &lt;key&gt;=&lt;value&gt;</code></td><td>Change a setting, such as <code>rdd set kubernetes.enabled=true</code></td></tr><tr><td><code>rdd svc delete</code></td><td>Stop the daemon and remove everything 2.0 created (also how you uninstall)</td></tr><tr><td><code>rdd ctl</code></td><td><code>kubectl</code> aimed at the <code>rdd</code> API, where Rancher Desktop keeps its own state</td></tr></tbody></table></div>
<style>
.command-reference td:first-child {
  white-space: nowrap;
}
</style>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/472" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-version-e85bc4">
<p>The file names in this post are Alpha 1's. Swap in the current version, <code>2.0.0-alpha.2</code>. <a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#user-content-fnref-version-e85bc4" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-linux-e85bc4">
<p>The packages come from the same openSUSE Build Service project as Rancher Desktop 1.x, <code>isv:Rancher:stable</code>. Add the repository as the <a class="" href="https://docs.rancherdesktop.io/getting-started/installation/">1.x installation guide</a> describes, then install <code>rancher-desktop-2</code>; the <code>rancher-desktop</code> package is 1.x. The project keeps only the newest build of each line, so Alpha 1 is no longer in it. <a href="https://docs.rancherdesktop.io/blog/installing-rancher-desktop-2/#user-content-fnref-linux-e85bc4" data-footnote-backref="" aria-label="Back to reference 2" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
        <item>
            <title><![CDATA[A Short History of Rancher Desktop]]></title>
            <link>https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/</link>
            <guid>https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/</guid>
            <pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[In October 2020, Rancher Desktop was a tray icon and a single shell command.]]></description>
            <content:encoded><![CDATA[<p>In October 2020, Rancher Desktop was a tray icon and a single shell command.
Click the icon, and it ran <code>minikube start</code> to bring up a Kubernetes cluster on
your Mac. The whole thing was nine files, one good idea, and a note in the
source that read, more or less, <em>this is just a quick proof of concept</em>.</p>
<p>SUSE had just bought Rancher Labs, and the goal was easy to state and hard to
build: make Kubernetes easy on a developer's laptop. We called it Rancher
Desktop because, at the time, "Rancher" was how SUSE said "Kubernetes." That
branding has gotten more complicated since, the way branding does, but the name
stuck.</p>
<p>About seven months later, in May 2021, the first public build shipped, with
macOS and Windows support, k3s<sup><a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fn-k3s-09d5bb" id="user-content-fnref-k3s-09d5bb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup> for Kubernetes, an image builder called kim<sup><a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fn-kim-09d5bb" id="user-content-fnref-kim-09d5bb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">2</a></sup>, and
a way to switch Kubernetes versions. It was alpha software and looked like it.
Five years on it's a different program, and the story of how it got here is
mostly the story of how much work it took to keep one simple promise on three
operating systems at once.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-operating-systems-two-backends">Two operating systems, two backends<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#two-operating-systems-two-backends" class="hash-link" aria-label="Direct link to Two operating systems, two backends" title="Direct link to Two operating systems, two backends" translate="no">​</a></h2>
<p>On a Mac, Kubernetes needs a Linux virtual machine. On Windows, it needs WSL2.
So from the very first release, Rancher Desktop had two backends, and we spent
the next five years discovering how different "two backends" really are.</p>
<p>The Mac side never sat still. We started with minikube, dropped it to drive
Apple's Hypervisor.framework via the docker-machine-driver-hyperkit, then
replaced it with Lima and QEMU<sup><a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fn-qemu-09d5bb" id="user-content-fnref-qemu-09d5bb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">3</a></sup>. Each move was a rebuild of the layer that
creates the VM, installs k3s, and wires up the network. When Apple later shipped
its own Virtualization framework, VZ, moving to it was mostly a matter of
telling Lima to use it.</p>
<p>Windows went its own way, with k3s running inside a dedicated WSL distribution
we imported from an image we built ourselves. When Linux arrived as a tech
preview in late 2021, it didn't add a third backend; it joined the Mac under
Lima, which manages the VM on macOS and Linux alike, and which we got to build
on as an upstream open-source project instead of maintaining alone. That part
worked out; macOS and Linux became one backend, where a fix landed once instead
of twice.</p>
<p>Building on Lima also meant helping to build it. Lima started narrow, just a
way to run containers with nerdctl on a Mac. The provisioning scripts we added
a few weeks in, the mechanism that runs setup inside a fresh VM, are how
Rancher Desktop installs k3s and a container engine. They also opened up Lima
so you could provision for almost anything. Other contributions are the
rules-based port forwarding configuration and host-based DNS lookup to extend
VPN connections into the VM. What we needed, we built upstream, where every
Lima user got to benefit from it.</p>
<p>Windows stayed separate. We tried more than once to fold the two together but
never fully managed it. The systems were too different: a VM you own end to end
on one side, a WSL distro living under someone else's rules on the other. So
most features had to be built twice, into two backends similar enough to look
the same and different enough to break in their own ways.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-small-guest-with-sharp-edges">A small guest with sharp edges<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#a-small-guest-with-sharp-edges" class="hash-link" aria-label="Direct link to A small guest with sharp edges" title="Direct link to A small guest with sharp edges" translate="no">​</a></h2>
<p>The VM ran Alpine Linux, picked because it's tiny, which meant a smaller
download and a faster boot. Alpine stays small by using musl<sup><a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fn-musl-09d5bb" id="user-content-fnref-musl-09d5bb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">4</a></sup> and OpenRC
instead of the glibc and systemd<sup><a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fn-init-09d5bb" id="user-content-fnref-init-09d5bb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">5</a></sup> most Linux software is built against.
Usually that difference is invisible, but sometimes it isn't. You can't run the
NVIDIA Container Toolkit on it, which means no CUDA, which means machines with
a GPU can't run the AI workloads people increasingly want to run. A choice that
saved a few megabytes early on walled off a whole category of work once GPUs
and AI showed up.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="more-than-kubernetes">More than Kubernetes<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#more-than-kubernetes" class="hash-link" aria-label="Direct link to More than Kubernetes" title="Direct link to More than Kubernetes" translate="no">​</a></h2>
<p>We set out to ship Kubernetes, and users kept asking for the rest of the
container toolbox. The first image builder, kim, ran inside the cluster; we
replaced it with nerdctl, the standard containerd CLI, and most people never
noticed kim was gone. Then we hit something we hadn't planned for; a lot of
real projects simply wouldn't build under nerdctl and buildkit. We added moby
(dockerd and the Docker CLI) as a second engine, so those projects would build.
Later we let people turn Kubernetes off entirely and run nothing but the
container engine. Rancher Desktop had quietly grown from "Kubernetes on your
desktop" into "containers and Kubernetes on your desktop."</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="networking-never-got-easy">Networking never got easy<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#networking-never-got-easy" class="hash-link" aria-label="Direct link to Networking never got easy" title="Direct link to Networking never got easy" translate="no">​</a></h2>
<p>Networking was the part that never stopped being hard. A container's ports, the
right DNS answers, a corporate VPN that doesn't break everything: getting all
three to coexist took years of work on each platform, and little of it carried
across. On macOS the VM reaches the network through a layer called vmnet<sup><a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fn-vmnet-09d5bb" id="user-content-fnref-vmnet-09d5bb" data-footnote-ref="true" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">6</a></sup>, where
we moved from one implementation to another and carried both for a while.
Windows needed something else entirely. WSL puts every distribution on one
shared network, so to avoid port conflicts with the others, we gave our VM a
tunnelling network in its own network namespace.</p>
<p>Some of that split is just the operating systems being different; there's no
single answer that works on both. A clean design can't avoid writing two of
them, so the question it has to get right is where that code should live,
pushed as far down into the shared foundation as it will go instead of tangled
through the app.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-people-actually-wanted">What people actually wanted<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#what-people-actually-wanted" class="hash-link" aria-label="Direct link to What people actually wanted" title="Direct link to What people actually wanted" translate="no">​</a></h2>
<p>The request for Linux support surprised us. On Linux you can already run k3s,
containerd, and Docker natively, so a desktop app doesn't add the containers.
Its value was being able to throw the whole thing away. A factory reset wipes
the VM back to nothing, worth a lot when your environment drifts into a state
you no longer understand. People wanted an undo button for their development
machine (and later, snapshots).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-backend-trapped-in-the-app">A backend trapped in the app<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#a-backend-trapped-in-the-app" class="hash-link" aria-label="Direct link to A backend trapped in the app" title="Direct link to A backend trapped in the app" translate="no">​</a></h2>
<p>Two features we built to make Rancher Desktop easier to work with ran into the
same limit.</p>
<p>rdctl was a command-line tool for driving Rancher Desktop without
touching the GUI. It let us write our integration tests as plain shell scripts
instead of clicking through the interface, and it let users automate their
setup. But not everything was reachable from it. Port forwarding, for one, still
went through private messaging between the GUI and the backend, never exposed
through the REST API, so the GUI could do things no script could.</p>
<p>Snapshots hit it too. Saving the VM's state to restore later was a simple
feature with an awkward implementation, because the backend has to stop while
its disk is copied, and the backend lives inside the GUI. So taking a snapshot
turned into a small contortion. The GUI launches rdctl, which calls back into
the GUI to ask it to shut its own backend down, takes the snapshot, then asks it
to start back up. Cancelling was worse. There was no clean channel for it, so
the GUI found the running rdctl process and killed it by name.</p>
<p>Underneath both was the same fact: you can't run the backend without the GUI.
You can hide the window, you can tuck it into the background, but the app is
always loaded, because the engine lives inside it. There is no headless Rancher
Desktop. For something a developer wants to script, drop on a CI runner, or hand
to an AI agent to drive, that's real friction.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-five-years-taught-us">What five years taught us<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#what-five-years-taught-us" class="hash-link" aria-label="Direct link to What five years taught us" title="Direct link to What five years taught us" translate="no">​</a></h2>
<p>Step back, and a pattern runs through all of it. Every feature got a little more
difficult to implement than the last. We had two backends to change in lockstep,
an engine welded to its own UI, and a guest OS that couldn't reach the GPU. None
of it was a mistake exactly (each call was reasonable when we made it), but the
costs compounded, until we were spending more time maintaining the existing
machinery than building anything new.</p>
<p>The parts that aged well point the way. Building on Lima gave us one backend for
macOS and Linux and an upstream community to share the load. And the
command-line tool we'd built for our own tests turned out to matter more than we
planned. A tool an AI model can explore and drive on its own is also exactly
what you want now that so much work is handed to agents.</p>
<p>So Rancher Desktop 2.0 starts over, on purpose. It runs one backend across every
platform (including Windows). The backend lives outside the UI now, so you can
run it on its own: headless, scripted, snapshotted by itself. And the guest can
talk to your GPU. The first five years weren't wrong; they taught us exactly
what the foundation needed to be. The rest of this blog is about what we're
building on it.</p>
<hr>
<p>💬 Questions or feedback? <strong><a href="https://github.com/rancher-sandbox/rancher-desktop-2/discussions/471" target="_blank" rel="noopener noreferrer" class="">Discuss this post on GitHub →</a></strong></p>
<!-- -->
<section data-footnotes="true" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-k3s-09d5bb">
<p>k3s is Rancher's lightweight Kubernetes distribution, small enough to run on a laptop or edge device. <a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fnref-k3s-09d5bb" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-kim-09d5bb">
<p>kim built images by running the build inside the Kubernetes cluster itself, not from a daemon on the host. It worked, but it tied image builds to a running cluster. <a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fnref-kim-09d5bb" data-footnote-backref="" aria-label="Back to reference 2" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-qemu-09d5bb">
<p>QEMU is an open-source machine emulator and virtualizer, here the software that created the Mac's Linux VM. <a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fnref-qemu-09d5bb" data-footnote-backref="" aria-label="Back to reference 3" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-musl-09d5bb">
<p>musl is a lightweight C library. Most prebuilt Linux binaries expect glibc, so software that assumes it can fail to start on Alpine without a compatibility shim. <a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fnref-musl-09d5bb" data-footnote-backref="" aria-label="Back to reference 4" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-init-09d5bb">
<p>systemd starts and supervises services on most Linux distributions. Alpine ships the lighter OpenRC instead, and a service written for one will not start under the other. <a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fnref-init-09d5bb" data-footnote-backref="" aria-label="Back to reference 5" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-vmnet-09d5bb">
<p>macOS gives a virtual machine its network through the vmnet framework. Which mode you pick mostly decides how the VM's addresses relate to the rest of your network. <a href="https://docs.rancherdesktop.io/blog/history-of-rancher-desktop/#user-content-fnref-vmnet-09d5bb" data-footnote-backref="" aria-label="Back to reference 6" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <author>jan.dubois@suse.com (Jan Dubois)</author>
        </item>
    </channel>
</rss>