<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://heaths.dev/feed.xml" rel="self" type="application/atom+xml"/><link href="https://heaths.dev/" rel="alternate" type="text/html"/><updated>2026-05-16T06:16:14+00:00</updated><id>https://heaths.dev/feed.xml</id><title type="html">Heath Stewart’s Blog</title><subtitle>Technical posts about my decades-long experience with installation, current news and information about my current role in Azure, and tips and tricks I&apos;ve picked up along the way. Occasionally about my backpacking and mountaineering adventures with friends and family.</subtitle><author><name>Heath Stewart</name></author><entry><title type="html">Initial stable release of Azure SDK for Rust</title><link href="https://heaths.dev/azure/2026/05/16/initial-stable-release-of-azure-sdk-for-rust.html" rel="alternate" type="text/html" title="Initial stable release of Azure SDK for Rust"/><published>2026-05-16T03:12:12+00:00</published><updated>2026-05-16T03:12:12+00:00</updated><id>https://heaths.dev/azure/2026/05/16/initial-stable-release-of-azure-sdk-for-rust</id><content type="html" xml:base="https://heaths.dev/azure/2026/05/16/initial-stable-release-of-azure-sdk-for-rust.html"><![CDATA[<p>I’m excited to announce our initial stable release of the <a href="https://devblogs.microsoft.com/azure-sdk/from-beta-to-stable-announcing-the-azure-sdk-for-rust-ga/">Azure SDK for Rust</a>! 🎉</p> <p>Besides the core libraries, we made the following crates generally available (GA):</p> <ul> <li><a href="https://crates.io/crates/azure_storage_blob">azure_storage_blob</a></li> <li><a href="https://crates.io/crates/azure_storage_queue">azure_storage_queue</a></li> <li><a href="https://crates.io/crates/azure_security_keyvault_secrets">azure_security_keyvault_secrets</a></li> <li><a href="https://crates.io/crates/azure_security_keyvault_keys">azure_security_keyvault_keys</a></li> <li><a href="https://crates.io/crates/azure_security_keyvault_certificates">azure_security_keyvault_certificates</a></li> </ul> <p><code class="language-plaintext highlighter-rouge">azure_data_cosmos</code> and <code class="language-plaintext highlighter-rouge">azure_messaging_eventhubs</code> will be available soon.</p> <h2 id="getting-started"><a href="#getting-started"></a>Getting Started</h2> <p>We have a lot of great examples in our <a href="https://docs.rs/azure_core"><code class="language-plaintext highlighter-rouge">azure_core</code></a> documentation. You can also find other <a href="https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/core/azure_core/examples"><code class="language-plaintext highlighter-rouge">azure_core</code> examples</a> in our <a href="https://github.com/Azure/azure-sdk-for-rust">repository</a>.</p> <h2 id="extensibility"><a href="#extensibility"></a>Extensibility</h2> <p>Rust doesn’t have a lot in its standard library - not even an async executor. Thus, applications need to pick an executor. While <a href="https://docs.rs/tokio">tokio</a> is the most common async executor - and on which our default HTTP client, <a href="https://docs.rs/reqwest"><code class="language-plaintext highlighter-rouge">reqwest</code></a> is based - there are other executors and HTTP clients applications may want to use. Azure service have to use a platform called Oxidizer - some of which is public - that provides an async executor optimized for running Azure services.</p> <p>Thus, we support <a href="https://docs.rs/azure_core/latest/azure_core/#replacing-the-http-client">replacing</a> the async executor and/or the HTTP client, along with customizing the default <code class="language-plaintext highlighter-rouge">reqwest::HttpClient</code> or even just <a href="https://docs.rs/azure_core/latest/azure_core/#adding-http-policies">adding HTTP policies</a> like with all our Azure SDK languages.</p> <p>See our cross-cutting <a href="https://github.com/Azure/azure-sdk-for-rust/tree/main/samples">samples</a>.</p> <h2 id="origins"><a href="#origins"></a>Origins</h2> <p>This started as passion project. I had been writing <a href="https://www.rust-lang.org">Rust</a> for a while but wanted something substantial to work on. I started the original Azure/azure-sdk-for-rust repo. Not long after, some colleagues heard about this and had been working on some unofficial crates that <a href="https://github.com/MindFlavor">MindFlavor</a> started. I ended up archiving my project and we forked his in its place. It went through a lot of changes to align with our Azure SDK <a href="https://azure.github.io/azure-sdk/general_introduction.html">general guidelines</a> while I started working on the initial <a href="https://azure.github.io/azure-sdk/rust_introduction.html">Rust guidelines</a>.</p> <p>As people moved on and the project was made official, I was named the architect and started prototyping many different ideas based on popular Rust projects. Anyone that tells you there is decidedly an “idiomatic Rust” is wrong. There are certainly common patterns, but with no clear language guidelines/recommendations like some other languages, there are lots of popular patterns from simple struct initialization, builders, typestate builders, and more. After going through some patterns with other architects, Rustaceans in the company, and people just starting to learn Rust - we want this to be approachable - we settled on a pattern.</p> <p>While I tried to maintain as much legacy as possible, some radical change was necessary. At that point, I moved the existing code to that point into the <a href="https://github.com/Azure/azure-sdk-for-rust/tree/legacy">legacy</a> branch. If we needed to make any critical security fixes, we still could. But development continued on in the <code class="language-plaintext highlighter-rouge">main</code> branch.</p> <h3 id="thanks"><a href="#thanks"></a>Thanks</h3> <p>I can’t thank enough the people who bootstrapped all this effort: Francesco, Ryan, Cameron, Brian, et. al. And for the people who took up the mantle when this was made an official project: Larry, Joel, Rick, Ashley, Anton, Ronnie, Patrick, Brian, et. al.</p> <div style="text-align: center;"> <picture> <source type="image/webp" srcset="/assets/images/rust-cake.webp"/> <img src="/assets/images/rust-cake.jpg"/> </picture> </div>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="azure"/><category term="rust"/><category term="rustlang"/><category term="azure-sdk"/><summary type="html"><![CDATA[I’m excited to announce our initial stable release of the Azure SDK for Rust! 🎉]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://heaths.dev/assets/images/rust-cake.jpg"/><media:content medium="image" url="https://heaths.dev/assets/images/rust-cake.jpg" xmlns:media="http://search.yahoo.com/mrss/"/></entry><entry><title type="html">Cooler theme palette</title><link href="https://heaths.dev/general/2026/05/03/cooler-theme-palette.html" rel="alternate" type="text/html" title="Cooler theme palette"/><published>2026-05-03T07:02:30+00:00</published><updated>2026-05-03T07:02:30+00:00</updated><id>https://heaths.dev/general/2026/05/03/cooler-theme-palette</id><content type="html" xml:base="https://heaths.dev/general/2026/05/03/cooler-theme-palette.html"><![CDATA[<p>The <a href="/general/2026/04/20/light-and-dark-themes-for-my-blog.html">Kraken-inspired theme</a> was fun for a time, but the dark theme contrast was a bit hard on the eyes and the light theme contrast was a little muted. So I wanted to try something a little different.</p> <h2 id="blue-hour"><a href="#blue-hour"></a>Blue Hour</h2> <p>I looked at a couple color palette sites for some color ideas then asked Copilot + Sonnet to work up a few color demos keeping accessibility in mind. From there I picked one I liked and had it update the necessary minima colors as well as replace the Kraken-inspired colors. It made re-theming the site pretty quick. I’m no designer, but it thought through accessibility and contrast issues I wouldn’t have considered.</p> <p>I think it turned out pretty good:</p> <p><img src="/assets/images/blue-hour-cover.jpg" alt="Screenshots of Blue Hour dark and light themes"/></p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="general"/><category term="blog"/><category term="css"/><category term="theme"/><summary type="html"><![CDATA[The Kraken-inspired theme was fun for a time, but the dark theme contrast was a bit hard on the eyes and the light theme contrast was a little muted. So I wanted to try something a little different.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://heaths.dev/assets/images/blue-hour-cover.jpg"/><media:content medium="image" url="https://heaths.dev/assets/images/blue-hour-cover.jpg" xmlns:media="http://search.yahoo.com/mrss/"/></entry><entry><title type="html">Improving the Azure SDK developer experience with MCP</title><link href="https://heaths.dev/azure/2026/05/01/improving-the-azure-sdk-developer-experience-with-mcp.html" rel="alternate" type="text/html" title="Improving the Azure SDK developer experience with MCP"/><published>2026-05-01T06:03:39+00:00</published><updated>2026-05-01T06:03:39+00:00</updated><id>https://heaths.dev/azure/2026/05/01/improving-the-azure-sdk-developer-experience-with-mcp</id><content type="html" xml:base="https://heaths.dev/azure/2026/05/01/improving-the-azure-sdk-developer-experience-with-mcp.html"><![CDATA[<p>The <a href="https://github.com/Azure/azure-sdk-for-rust">Azure SDK for Rust</a> has been in active development for about two years now and will be releasing 1.0.0 soon. A lot has changed since the beginning, and the training data for even modern models shows that. When given enough context to recognize the API, it uses outdated patterns and even APIs that have been removed, renamed, or otherwise changed.</p> <p>Even for more established Azure SDK languages like <a href="https://github.com/Azure/azure-sdk-for-net">.NET</a> or <a href="https://github.com/Azure/azure-sdk-for-python">Python</a>, new APIs might be added to a particular service or new patterns may evolve that are better to use.</p> <p>Whatever the case, additional context can improve productivity and reduce cost.</p> <h2 id="example-context"><a href="#example-context"></a>Example context</h2> <p>I wrote an <a href="https://github.com/heaths/azsdk-samples-mcp">MCP</a> that discovers Azure SDK dependencies already pulled down, and adds their <code class="language-plaintext highlighter-rouge">README.md</code> and other regocnized examples - like Rust’s <code class="language-plaintext highlighter-rouge">examples/</code> directory that is included in our crates - and adds them as context. As the demo video below shows, this greatly reduces the number of turns for Rust, thereby reducing the token count and cost:</p> <div class="youtube-container"> <iframe src="https://www.youtube.com/embed/MAhdQDmkZOs" title="Azure SDK Samples MCP Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""> </iframe> </div> <p>As a successful prototype, there is still more we can improve on here like distilling the examples from the <code class="language-plaintext highlighter-rouge">README.md</code> instead of sending the entire page. Taking advantage of memory in modern agents, we could also link general patterns like those found in our core libraries e.g., <a href="https://docs.rs/azure_core"><code class="language-plaintext highlighter-rouge">azure_core</code></a> for Rust.</p> <p>I’m excited to see how we can apply findings from this prototype to further improve the developer experience when using Azure SDKs!</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="azure"/><category term="azure-sdk"/><category term="mcp"/><category term="rustlang"/><category term="experiment"/><summary type="html"><![CDATA[The Azure SDK for Rust has been in active development for about two years now and will be releasing 1.0.0 soon. A lot has changed since the beginning, and the training data for even modern models shows that. When given enough context to recognize the API, it uses outdated patterns and even APIs that have been removed, renamed, or otherwise changed.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://heaths.dev/assets/images/mcp-demo-01.jpg"/><media:content medium="image" url="https://heaths.dev/assets/images/mcp-demo-01.jpg" xmlns:media="http://search.yahoo.com/mrss/"/></entry><entry><title type="html">Light and dark themes for my blog</title><link href="https://heaths.dev/general/2026/04/20/light-and-dark-themes-for-my-blog.html" rel="alternate" type="text/html" title="Light and dark themes for my blog"/><published>2026-04-20T06:48:45+00:00</published><updated>2026-04-20T06:48:45+00:00</updated><id>https://heaths.dev/general/2026/04/20/light-and-dark-themes-for-my-blog</id><content type="html" xml:base="https://heaths.dev/general/2026/04/20/light-and-dark-themes-for-my-blog.html"><![CDATA[<p><img src="/assets/images/kraken-theme.jpg" alt="A blog page shown in both light and dark themes side by side, using the Seattle Kraken color palette"/></p> <p>My posts will always be written by me, a human, sharing tips, personal news, and more. And though I started writing web sites before HTML 1.0 was formally standardized, I’ve never been good at design. My blog used Jekyll Minima with a few overrides and I only recently updated it to 2.5, but was envious of the theming that 3.0 has in development. Though I really haven’t touched much CSS since shortly after 2.0 was released, I knew the mechanics but wanted a little help prototyping some ideas quickly.</p> <h2 id="trying-out-themes"><a href="#trying-out-themes"></a>Trying out themes</h2> <p>It probably wasn’t obvious, but my previous color palette used Seahawks colors. I wanted to see what mixing those colors or other colors might look like for light and dark themes. With some links to the color palettes I was considering - but haven’t necessarily settled on for the foreseeable future - asked Copilot with Sonnet 4.6 to render a few. It didn’t take long - certainly faster than I’d have done it - and I was able to select a theme as a start quickly. I made a few tweaks and had it apply the changes with some color mapping instructions from the old palette.</p> <p>Having been to several of their games with my son - who loves hockey - and my wife - who merely tolerated it but got a selfie with Buoy - I choose a Kraken color palette. They put on one heck of a show at Climate Pledge Arena.</p> <p>It took a few iterations to iron out the kinks. I would verify the responsive site in Safari’s dev tools and batch several changes with explicit instructions. As with any time I use an LLM to generate code, I review and recommend changes as needed.</p> <h2 id="theme-switcher-and-responsive-fixes"><a href="#theme-switcher-and-responsive-fixes"></a>Theme switcher and responsive fixes</h2> <p>With separate light and dark themes, I next had it lay the ground work to switch themes and fix some responsive issues, like certain buttons being too long on mobile viewports so I’d change the text to “Subscribe” instead of “Subscribe on Sequoia” in the <code class="language-plaintext highlighter-rouge">sequoia-subscribe</code> component. Again, with a carefully crafted prompt, it didn’t take long to generate the necessary changes that’d probably have taken me a couple hours.</p> <p>With all changes reviewed and tested, I finally had a properly responsive and themed web site I’ve been wanting but just haven’t found the time.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="general"/><category term="blog"/><category term="copilot"/><category term="css"/><summary type="html"><![CDATA[]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://heaths.dev/assets/images/kraken-theme.jpg"/><media:content medium="image" url="https://heaths.dev/assets/images/kraken-theme.jpg" xmlns:media="http://search.yahoo.com/mrss/"/></entry><entry><title type="html">We all make mistakes</title><link href="https://heaths.dev/general/2026/04/18/we-all-make-mistakes.html" rel="alternate" type="text/html" title="We all make mistakes"/><published>2026-04-18T07:24:41+00:00</published><updated>2026-04-18T07:24:41+00:00</updated><id>https://heaths.dev/general/2026/04/18/we-all-make-mistakes</id><content type="html" xml:base="https://heaths.dev/general/2026/04/18/we-all-make-mistakes.html"><![CDATA[<p>After 15 years in Visual Studio and having shipped a few versions of the new setup engine I architected as a senior engineer at Microsoft, it was time for a change. I was a few weeks into my new job on the Azure SDK for .NET team as, among other responsibilities, the technical lead on the Key Vault SDK virtual team.</p> <p>I was also working on an idea for <a href="https://github.com/Azure/azure-sdk-for-net/blob/941cc979bf7b36cb9592888d8397f23b2b10f5bd/eng/common/TestResources/README.md">unified test resource provisioning</a> across SDKs and languages and was working with a couple different vaults in the Azure Portal: our test secrets used by all the languages, and one I had just created for some tests. Certain I had the right one selected, I was prompted <strong>Are you sure you want to delete this vault?</strong> with just <strong>Yes</strong> and <strong>No</strong> buttons, and clicked <strong>Yes</strong>.</p> <p>I was wrong.</p> <p>I deleted the shared test secrets used by Azure Pipelines and more.</p> <p>Within seconds I realized my mistake, hurried down the hall to our engineering systems team room, and echoed <a href="https://en.wikipedia.org/wiki/George_Oscar_Bluth_II">Gob Bluth</a>’s famous line, “I’ve made a huge mistake.”</p> <p>Not the best start on a new team, but what happened next is what I like to share with mentees both junior and senior.</p> <h2 id="driving-change"><a href="#driving-change"></a>Driving change</h2> <p>In the short term, we needed to restore functionality. Soft delete wasn’t enabled on the vault, so the vault was truly gone. But across all the developers, we all had enough secrets in process or machine environment variables<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> that we could restore most of the secrets. Others we just had to regenerate and deal with as problems arose.</p> <p>In the long term, I wanted to make sure something so vital - think about a company losing production secrets on which their business depends - didn’t happen again, or at least wasn’t so easy.</p> <p>I had already developed a pretty good rapport with the Key Vault service team, and worked with them on some changes:</p> <ol> <li>The name of the vault wasn’t part of the original prompt. They added the name of the vault and changed the buttons to more descriptive <strong>Delete</strong> and <strong>Cancel</strong>.</li> <li> <p>They moved up plans to enable soft delete by default. After that change, you had to explicitly disable soft delete. Seems many customers weren’t aware of soft delete, which allows you to recover a deleted vault or vault resource for a configured number of days - the default being 90 days.</p> <p>Eventually, a change was made such that soft delete couldn’t be disabled, and purge protection could be enabled that prevented a deleted vault or vault resource from being purged for the configured number of days.</p> </li> </ol> <h2 id="final-thoughts"><a href="#final-thoughts"></a>Final thoughts</h2> <p>We all make mistakes. I was a senior at the time and not long after that was promoted to a principal engineer. I still make mistakes - perhaps not as bad and hopefully won’t - but how we deal with them and learn from them is what matters.</p> <p>Own up to the mistake and try to prevent them from happening again or to anyone else, if relevant. Seek out partners to brainstorm ideas and show a growth mindset among your peers and management. They’ve all made mistakes too.</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:1"> <p>We later changed how authentication was done and moved non-secrets into normal configuration variables. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="general"/><category term="about"/><category term="azure"/><category term="mentoring"/><category term="story"/><summary type="html"><![CDATA[After 15 years in Visual Studio and having shipped a few versions of the new setup engine I architected as a senior engineer at Microsoft, it was time for a change. I was a few weeks into my new job on the Azure SDK for .NET team as, among other responsibilities, the technical lead on the Key Vault SDK virtual team.]]></summary></entry><entry><title type="html">Making the key version required for Key Vault cryptography APIs</title><link href="https://heaths.dev/azure/2026/04/08/making-the-key-version-required-for-key-vault-cryptography-apis.html" rel="alternate" type="text/html" title="Making the key version required for Key Vault cryptography APIs"/><published>2026-04-08T05:32:00+00:00</published><updated>2026-04-08T05:32:00+00:00</updated><id>https://heaths.dev/azure/2026/04/08/making-the-key-version-required-for-key-vault-cryptography-apis</id><content type="html" xml:base="https://heaths.dev/azure/2026/04/08/making-the-key-version-required-for-key-vault-cryptography-apis.html"><![CDATA[<p>When I started on the Azure SDK team almost 7 years ago, I immediately jumped into the Azure Key Vault SDK for .NET among other responsibilities. We already had a pretty good codebase as a start lead by a former colleague who worked in Azure Key Vault prior to joining the Azure SDK team.</p> <p>Since the Key Vault service allowed an empty string for the key version for all endpoints, the KV SDKs across all languages back then - <a href="https://github.com/Azure/azure-sdk-for-net">.NET</a>, <a href="https://github.com/Azure/azure-sdk-for-java">Java</a>, <a href="https://github.com/Azure/azure-sdk-for-js">JavaScript/TypeScript</a>, and <a href="https://github.com/Azure/azure-sdk-for-python">Python</a> - we made the key version parameters in all those languages optional even though they didn’t all technically follow language guidelines for optional parameters: optional parameters go into “options bags” - an optional parameter that had a bunch of optional properties on it or, for pythonistas, <code class="language-plaintext highlighter-rouge">kwargs</code>.</p> <p>For key data operations that generally fine: an empty version means you act on the latest key version; however, for cryptography operations - encrypt, decrypt, sign, verify, wrap, and unwrap - that can inadvertently lock you out of your data. For example, if you encrypt with key version 1 and that key is rotated to version 2, you won’t be able to decrypt with version 2. You can work around this by cycling through key versions, but knowing when you found the right one isn’t always easy if you don’t know the plaintext. This is compounded when unwrapping a symmetric key because the key length is the same and, in some block ciphers, will decrypt into plaintext you can’t always validate.</p> <h2 id="required-for-rust"><a href="#required-for-rust"></a>Required for Rust</h2> <p>Since I’m the architect for the <a href="https://github.com/Azure/azure-sdk-for-rust">Azure SDK for Rust</a>, have much more experience with Azure Key Vault now, and have been working on the Key Vault SDKs for Rust, after having talked with the Key Vault service team about it, we made the key version parameter required for cryptography operations. Not only does this mean the version parameters actually follow <a href="https://azure.github.io/azure-sdk/rust_introduction.html#rust-client-methods">language guidelines</a>, but that they steer customers into the pit of success. You can still pass an empty string <code class="language-plaintext highlighter-rouge">""</code> to use the latest version but it’s not recommended.</p> <p>I’ve <a href="https://github.com/heaths/akv-cli-rs/pull/111">updated</a> the <a href="https://github.com/heaths/akv-cli-rs">akv CLI</a> accordingly to require the key version for the <code class="language-plaintext highlighter-rouge">encrypt</code> command, whether passed to <code class="language-plaintext highlighter-rouge">--version</code> or (new) passed as a key URI with version.</p> <p>Hopefully by requiring a key version for crypto functions, customers will be less likely to accidentally lock themselves out of their encrypted data.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="azure"/><category term="azure"/><category term="cryptography"/><category term="keyvault"/><category term="rustlang"/><summary type="html"><![CDATA[When I started on the Azure SDK team almost 7 years ago, I immediately jumped into the Azure Key Vault SDK for .NET among other responsibilities. We already had a pretty good codebase as a start lead by a former colleague who worked in Azure Key Vault prior to joining the Azure SDK team.]]></summary></entry><entry><title type="html">Cleaning up Rust made easier</title><link href="https://heaths.dev/rust/2026/03/21/cleaning-up-rust-made-easier.html" rel="alternate" type="text/html" title="Cleaning up Rust made easier"/><published>2026-03-21T06:14:00+00:00</published><updated>2026-03-21T06:14:00+00:00</updated><id>https://heaths.dev/rust/2026/03/21/cleaning-up-rust-made-easier</id><content type="html" xml:base="https://heaths.dev/rust/2026/03/21/cleaning-up-rust-made-easier.html"><![CDATA[<p>WSL distributions are installed into VHDX files that, by default, automatically expand up to the amount of drive space on which they are stored - your system drive, by default. Some toolchains like Rust tend to fill up that space pretty quickly. If you don’t delete older dependencies from <code class="language-plaintext highlighter-rouge">~/.cargo</code> often or keep <code class="language-plaintext highlighter-rouge">targets/</code> for a long time across multiple toolchain versions or target architectures, that space will fill up quickly.</p> <p>Using <a href="https://crates.io/crates/cargo-cache"><code class="language-plaintext highlighter-rouge">cargo-cache</code></a> as I <a href="/rust/2025/03/01/cleaning-up-rust.html">described previously</a> can help clean up old dependencies, and you can delete all <code class="language-plaintext highlighter-rouge">targets/</code> from repos under some directory like so:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>find <span class="nt">-maxdepth</span> 2 <span class="nt">-name</span> targets <span class="nt">-execdir</span> <span class="nb">rm</span> <span class="nt">-rf</span> <span class="o">{}</span> <span class="se">\;</span>
</code></pre></div></div> <p>After that and cleaning up any other files you don’t need, log out of all your WSL sessions, close down Visual Studio Code if you have it running and connected to WSL e.g., if you started <code class="language-plaintext highlighter-rouge">code</code> from within WSL, and shut down WSL:</p> <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wsl</span><span class="w"> </span><span class="nt">--shutdown</span><span class="w">
</span></code></pre></div></div> <p>Now for the easier part: find the VHDX for your distro and shrink it all from within PowerShell:</p> <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Replace "Ubuntu-24.04" with your distro name</span><span class="w">
</span><span class="nv">$path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Get-ChildItem</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nx">HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="o">|</span><span class="w"> </span><span class="n">Where-Object</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="bp">$_</span><span class="o">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="s2">"DistributionName"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s1">'Ubuntu-24.04'</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="se">`</span><span class="w">
  </span><span class="p">)</span><span class="o">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="s2">"BasePath"</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">"\ext4.vhdx"</span><span class="w">
</span><span class="n">Optimize-VHDX</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nv">$path</span><span class="w">
</span></code></pre></div></div> <p>It may take a while, but after it completes you can log back into your distro. Seems WSL changed it so you don’t have to run <code class="language-plaintext highlighter-rouge">resize2fs</code> anymore - Ubuntu 24.04, at least, automatically picked up that more space was available.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="rust"/><category term="rustlang"/><category term="tips"/><category term="wsl"/><summary type="html"><![CDATA[WSL distributions are installed into VHDX files that, by default, automatically expand up to the amount of drive space on which they are stored - your system drive, by default. Some toolchains like Rust tend to fill up that space pretty quickly. If you don’t delete older dependencies from ~/.cargo often or keep targets/ for a long time across multiple toolchain versions or target architectures, that space will fill up quickly.]]></summary></entry><entry><title type="html">Publishing to the ATmosphere</title><link href="https://heaths.dev/atproto/2026/02/21/publishing-to-the-atmosphere.html" rel="alternate" type="text/html" title="Publishing to the ATmosphere"/><published>2026-02-21T04:00:00+00:00</published><updated>2026-02-21T04:00:00+00:00</updated><id>https://heaths.dev/atproto/2026/02/21/publishing-to-the-atmosphere</id><content type="html" xml:base="https://heaths.dev/atproto/2026/02/21/publishing-to-the-atmosphere.html"><![CDATA[<p>I’ve been reading a lot about <a href="https://atproto.com">ATProto</a> and following many accounts on <a href="https://bsky.app">Bluesky</a> like <a href="https://threddyrex.org">@threddyrex.org</a> with interest. I had been following <a href="https://standard.site">standard.site</a> as well and started thinking about how I might publish records using its lexicon to my hosted PDS. Then I discovered <a href="https://sequoia.pub">Sequoia</a>!</p> <p>It’s a CLI that works with various static-site generators to publish records into your PDS - something I was just starting to think how I wanted to tackle it. This CLI is a good start, so I’m happy to try it out, file bugs, and even submit pull requests!</p> <p>This post, if all is set up correctly, should be the first post published to the ATmosphere.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="atproto"/><category term="atproto"/><category term="jekyll"/><summary type="html"><![CDATA[I’ve been reading a lot about ATProto and following many accounts on Bluesky like @threddyrex.org with interest. I had been following standard.site as well and started thinking about how I might publish records using its lexicon to my hosted PDS. Then I discovered Sequoia!]]></summary></entry><entry><title type="html">Cross-compiling x64 on Aarch64</title><link href="https://heaths.dev/rust/2025/05/11/cross-compiling-x64-on-aarch64.html" rel="alternate" type="text/html" title="Cross-compiling x64 on Aarch64"/><published>2025-05-11T01:39:18+00:00</published><updated>2025-05-11T01:39:18+00:00</updated><id>https://heaths.dev/rust/2025/05/11/cross-compiling-x64-on-aarch64</id><content type="html" xml:base="https://heaths.dev/rust/2025/05/11/cross-compiling-x64-on-aarch64.html"><![CDATA[<p>Cross-compiling in Rust is generally pretty easy:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rustup target add x86_64-unknown-linux-gnu
cargo build <span class="nt">--target</span> x86_64-unknown-linux-gnu
</code></pre></div></div> <p>Of course, the targets’ compiler, headers, and libraries need to be available, but a typical install of <a href="https://www.visualstudio.com">Visual Studio</a> or gcc will support common targets. But on my new work Surface Laptop 7 arm64 I needed to compile <code class="language-plaintext highlighter-rouge">openssl-sys</code> for <a href="https://github.com/heaths/akv-cli-rs">my a project</a> and that’s when the fun began:</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>error: failed to run custom build command for `openssl-sys v0.9.102`

----- SNIP ---8&lt;
  cargo:rerun-if-env-changed=OPENSSL_DIR
  OPENSSL_DIR unset
</code></pre></div></div> <p>While there are lots of ways of getting the bits I need - like compiling source myself or downloading and extracting files to the right locations - I like the convenience of a package manager especially when it comes to installing updates. But I’m running Ubuntu 24.04 aarch64, so how do I install packages for amd64 e.g., <code class="language-plaintext highlighter-rouge">libssl-dev:amd64</code>?</p> <h2 id="configuring-sources"><a href="#configuring-sources"></a>Configuring sources</h2> <p>While I’ve had some experience managing debian package repositories e.g., in <code class="language-plaintext highlighter-rouge">/etc/apt/</code> I’ve never before had need to try to install packages for other architectures. I wasn’t even entirely sure it was supported, but a quick search got me started:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>dpkg <span class="nt">--add-architecture</span> amd64
<span class="nb">sudo </span>apt update
</code></pre></div></div> <p>But updating the package index failed: I was getting several 404s because packages weren’t available on <a href="http://ports.ubuntu.com/ubuntu-ports/">http://ports.ubuntu.com/ubuntu-ports/</a>. I was also only familiar with the one-line format and not this new format I was seeing, which `man 5 sources.list tells me is DEP822-style.</p> <p>After reading <code class="language-plaintext highlighter-rouge">sources.list(5)</code> and a bit of trial and error, I ended up with the following <code class="language-plaintext highlighter-rouge">/etc/apt/sources.list.d/ubuntu.sources</code></p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Types: deb
URIs: http://ports.ubuntu.com/ubuntu-ports/
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Architectures: arm64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Architectures: amd64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://ports.ubuntu.com/ubuntu-ports/
Suites: noble-security
Components: main universe restricted multiverse
Architectures: arm64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble-security
Components: main universe restricted multiverse
Architectures: amd64
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
</code></pre></div></div> <h2 id="installing-packages"><a href="#installing-packages"></a>Installing packages</h2> <p>After a quick and finally successful <code class="language-plaintext highlighter-rouge">sudo apt update</code>, I was able to install packages:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">--yes</span> libssl-dev:amd64
</code></pre></div></div> <p>I was able to get further with my original goal of compiling <code class="language-plaintext highlighter-rouge">openssl-sys</code>, but then got an error about no linker available. I installed <code class="language-plaintext highlighter-rouge">gcc:amd64</code> and almost able to compile my crate, but the linker failed so I needed to specify the linker explicitly in <code class="language-plaintext highlighter-rouge">.cargo/config.toml</code>:</p> <div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">[</span><span class="n">tageet</span><span class="k">.</span><span class="n">aarch64-unknown-linux-gnu</span><span class="k">]</span>
<span class="n">linker</span> <span class="o">=</span><span class="w"> </span><span class="s">"aarch64-linux-gnu-gcc"</span>

<span class="k">[</span><span class="n">target</span><span class="k">.</span><span class="n">x86_64-unknown-linux-gnu</span><span class="k">]</span>
<span class="n">linker</span> <span class="o">=</span><span class="w"> </span><span class="s">"x86_64-linux-gnu-gcc"</span>
</code></pre></div></div> <p>Success! …well, almost.</p> <p>When I tried a normal build e.g., <code class="language-plaintext highlighter-rouge">cargo build</code> I got pages full of compiler errors. Turns out, when I installed <code class="language-plaintext highlighter-rouge">gcc:amd64</code> it replace a few components, since <code class="language-plaintext highlighter-rouge">apt list --installed *gcc</code> showed <code class="language-plaintext highlighter-rouge">gcc-13-aarch64-linux-gnu</code> was now removable.</p> <p>After a quick search - there’s plenty of information of people wanting to cross-compile for aarch64 on amd64 - I realized I need to install a few packages at once, to effectively make sure all the right symlinks are created. I could’ve done this manually, but figured there were a number of executables I’d need to fix and would rather just let <code class="language-plaintext highlighter-rouge">apt</code> handle it:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install</span> <span class="nt">--yes</span> gcc-13 gcc-13-aarch64-linux-gnu gcc-13-x86-64-linux-gnu
<span class="nb">sudo ln</span> <span class="nt">-s</span> /usr/bin/x86_64-linux-gnu-gcc /usr/bin/x86_64-linux-gnu-gcc-13
</code></pre></div></div> <p>The last line was just for convenience, which <code class="language-plaintext highlighter-rouge">apt</code> did for <code class="language-plaintext highlighter-rouge">aarch64-linux-gnu-gcc</code> and, originally, when I installed <code class="language-plaintext highlighter-rouge">gcc-13-x86-64-linux-gnu</code> standalone.</p> <h2 id="cross-compiling-for-openssl-sys"><a href="#cross-compiling-for-openssl-sys"></a>Cross-compiling for openssl-sys</h2> <p>I was finally able to cross-compile <code class="language-plaintext highlighter-rouge">openssl-sys</code>:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo build
<span class="nv">PKG_CONFIG_SYSROOT_DIR</span><span class="o">=</span>/usr/lib/x86_64-linux-gnu cargo build <span class="nt">--target</span> x86_64-unknown-linux-gnu
</code></pre></div></div>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="rust"/><category term="gcc"/><category term="rustlang"/><category term="tips"/><category term="wsl"/><summary type="html"><![CDATA[Cross-compiling in Rust is generally pretty easy:]]></summary></entry><entry><title type="html">Cleaning up Rust</title><link href="https://heaths.dev/rust/2025/03/01/cleaning-up-rust.html" rel="alternate" type="text/html" title="Cleaning up Rust"/><published>2025-03-01T05:10:00+00:00</published><updated>2025-03-01T05:10:00+00:00</updated><id>https://heaths.dev/rust/2025/03/01/cleaning-up-rust</id><content type="html" xml:base="https://heaths.dev/rust/2025/03/01/cleaning-up-rust.html"><![CDATA[<p>I’m the lead developer on the <a href="https://github.com/Azure/azure-sdk-for-rust">Azure SDK for Rust</a> and have been working on it for a few years now. I also started or contribute to a number of other <a href="https://www.rust-lang.org">Rust</a> projects. With all the different crates and numerous versions of the same crate names, a lot of drive space is lost to downloaded crates and cloned - but shallow - repos. When I switch branches that might use different versions or features of crates, it also uses a lot of drive space.</p> <p>Fortunately, cleaning up all that Rust doesn’t require WD-40 and a little elbow grease. Here are a few tips:</p> <ol> <li> <p>Use <a href="https://crates.io/crates/cargo-cache">cargo-cache</a> to view information about and clean up the cargo cache:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo <span class="nb">install </span>cargo-cache
cargo cache <span class="nt">--info</span>
cargo cache <span class="nt">--help</span>
</code></pre></div> </div> <p>It hasn’t been updated in a while, but seems to work quite well.</p> </li> <li> <p>Delete your <code class="language-plaintext highlighter-rouge">target/</code> directory. Generally, most of the time building is spent acquiring crates anyway, but this can typically save you a lot of space, especially if you’ve been working in a repo for a while and dependencies have changed frequently.</p> </li> </ol> <h2 id="wsl"><a href="#wsl"></a>WSL</h2> <p>This can be even more problematic when working in Windows Subsystem for Linux (WSL), since the virtual hard disk (VHDX) used to default to 256GB then later 512GB, and currently 1TB. Note, however, this is only the maximum size the VHDX sees as the maximum space. Depending on your physical drive space availability, it may be less.</p> <p>In my case, recently, my old WSL Ubuntu-22.04 image thought it ran out because it only saw 256GB. Most of that was consumed by Rust and Go. You can view space using <code class="language-plaintext highlighter-rouge">du</code> from within WSL like so:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">du</span> <span class="nt">-hd1</span> <span class="nt">-t1gb</span> <span class="nb">.</span>
</code></pre></div></div> <p>If deleting repos’ <code class="language-plaintext highlighter-rouge">target/</code> directories didn’t free enough space, you can <a href="https://learn.microsoft.com/windows/wsl/disk-space">resize your VHDX</a> from an elevated shell:</p> <div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Replace 'Ubuntu-22.04' below with the name of your distro.</span><span class="w">

</span><span class="c"># Shut down your distro.</span><span class="w">
</span><span class="n">wsl</span><span class="w"> </span><span class="nt">--shutdown</span><span class="w"> </span><span class="s1">'Ubuntu-22.04'</span><span class="w">

</span><span class="c"># Find the path to the VHDX file for your distro.</span><span class="w">
</span><span class="p">(</span><span class="n">Get-ChildItem</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nx">HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss</span><span class="w"> </span><span class="se">`
</span><span class="w">  </span><span class="o">|</span><span class="w"> </span><span class="n">Where-Object</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="bp">$_</span><span class="o">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="s2">"DistributionName"</span><span class="p">)</span><span class="w"> </span><span class="o">-eq</span><span class="w"> </span><span class="s1">'Ubuntu-22.04'</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="se">`</span><span class="w">
  </span><span class="p">)</span><span class="o">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="s2">"BasePath"</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">"\ext4.vhdx"</span><span class="w">

</span><span class="c"># Launch diskpart and resize the disk returned above as {path}.</span><span class="w">
</span><span class="n">diskpart</span><span class="w">
</span><span class="nx">select</span><span class="w"> </span><span class="nx">vdisk</span><span class="w"> </span><span class="nx">file</span><span class="o">=</span><span class="s2">"{path}"</span><span class="w">
</span><span class="n">expand</span><span class="w"> </span><span class="nx">vdisk</span><span class="w"> </span><span class="nx">maximum</span><span class="o">=</span><span class="s2">"{size in MB}"</span><span class="w">
</span><span class="kr">exit</span><span class="w">
</span></code></pre></div></div> <p>Now log into your distro’s shell again and tell it that it has more disk space available:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Find the correct device.</span>
<span class="nb">sudo </span>mount <span class="nt">-t</span> devtmpfs none /dev 2&gt; /dev/null
mount | <span class="nb">grep </span>ext4

<span class="c"># Copy the name e.g., /dev/sdc and resize it using the same size in MB as above.</span>
<span class="nb">sudo </span>resize2fs /dev/sdb <span class="s1">'{size in MB}M'</span>
</code></pre></div></div>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;mrhestew&quot;, &quot;picture&quot;=&gt;&quot;/assets/images/headshot.jpg&quot;}</name></author><category term="rust"/><category term="rustlang"/><category term="tips"/><category term="wsl"/><summary type="html"><![CDATA[I’m the lead developer on the Azure SDK for Rust and have been working on it for a few years now. I also started or contribute to a number of other Rust projects. With all the different crates and numerous versions of the same crate names, a lot of drive space is lost to downloaded crates and cloned - but shallow - repos. When I switch branches that might use different versions or features of crates, it also uses a lot of drive space.]]></summary></entry></feed>