fasterthanli.me amos likes to tinker https://fasterthanli.me/ 2024-11-23T17:40:00Z Amos Wenger https://fasterthanli.me told https://cdn.fasterthanli.me/content/img/logo-square-2~12319eaafaaf55d3.png Highlighted code in slides https://fasterthanli.me/articles/highlighted-code-in-slides 2024-11-23T17:40:00Z <p data-bo="223">I have obsessed about this long enough, I think it&#x27;s only fair I (and you!) get some content out of it.</p> <p data-bo="328">When I started writing this article, I was working on my <a href="https://p99conf.io">P99 CONF</a> slides. Those slides happen to include some bits of code. And because I&#x27;m a perfectionist, I would like this code to be syntax highlighted, like this:</p> <code class="code-block has-language-tag" translate="no" data-lang="rust""><label class="language-tag" title="Rust"></label><pre class="scroll-wrapper"><i class=hh4>let</i> addr<i class=hh9>:</i> <i class=hh13>SocketAddr</i> = config<i class=hh9>.</i><i class=hh6>address</i><i class=hh9>.</i><i class=hh3>parse</i><i class=hh8>(</i><i class=hh8>)</i>?<i class=hh9>;</i> <i class=hh4>let</i> ln = <i class=hh13>TcpListener</i><i class=hh9>::</i>addr? configbase_url </pre></code> <!-- playwall --> ktls now under the rustls org https://fasterthanli.me/articles/ktls-now-under-rustls-org 2024-09-26T21:10:00Z <a id="what-s-a-ktls" href="#what-s-a-ktls" class="anchor"><h2>What&#x27;s a ktls</h2></a> <p data-bo="151">I started work on <a href="https://crates.io/crates/ktls">ktls</a> and <a href="https://crates.io/crates/ktls-sys">ktls-sys</a>, a pair of crates exposing <a href="https://www.kernel.org/doc/html/latest/networking/tls-offload.html">Kernel TLS offload</a> to Rust, about <a href="https://github.com/rustls/ktls/commit/798466d7c3e659ecdf035afac0bea2b679aea4c4">two years ago</a>.</p> <p data-bo="486">kTLS lets the kernel (and, in turn, any network interface that supports it) take care of encryption, framing, etc., for the entire duration of a TLS connection... as soon as you <em>have</em> a TLS connection.</p> <p data-bo="690">For the handshake itself (hellos, change cipher, encrypted extensions, certificate verification, etc.), you still have to use a userland TLS implementation.</p> State of the fasterthanlime 2024 https://fasterthanli.me/articles/state-of-the-fasterthanlime-2024 2024-08-07T07:14:05Z <p data-bo="133">It&#x27;s time for some personal <em>and</em> professional news!</p> <p data-bo="187">TL;DR: I started <a href="https://sdr-podcast.com">a podcast</a> with <a href="https://jamesmunns.com/contact/">James</a>, I&#x27;m stable on antidepressants, I&#x27;m giving a <a href="https://www.p99conf.io/">P99 CONF</a> about my <a href="https://github.com/bearcove/fluke">Rust&#x2F;io_uring&#x2F;HTTP work</a>, I&#x27;m trying on &quot;they&#x2F;them&quot; as pronouns, I&#x27;m open-sourcing <a href="https://github.com/bearcove/merde_json">merde_json</a>, <a href="https://github.com/bearcove/rubicon">rubicon</a> and others, I got a divorce in 2023, I found a new business model.</p> <p data-bo="665">Now that we&#x27;re on the same page: let&#x27;s unpack this a bit!</p> Face cams: the missing guide https://fasterthanli.me/articles/face-cams-the-missing-guide 2024-03-02T18:00:00Z <p data-bo="129">I try to avoid doing &quot;meta&quot; &#x2F; &quot;behind the scenes&quot; stuff, because I usually feel like it has to be &quot;earned&quot;. How many YouTube channels are channels about making YouTube videos? Too many.</p> <p data-bo="316">Regardless, because I&#x27;ve had the opportunity to make my own mistakes now for a few years (I started <a href="https://www.youtube.com/@fasterthanlime">doing the video thing</a> in earnest in 2019), and because I&#x27;ve recently made a few leaps in quality-of-life re: shooting and editing video, I thought I&#x27;d publish a few notes, if only for reference for my future self.</p> Just paying Figma $15/month because nothing else fucking works https://fasterthanli.me/articles/just-paying-figma-15-dollars 2023-10-19T16:50:00Z <p data-bo="168">My family wasn&#x27;t poor by any stretch of the imagination, but I was raised to avoid spending money whenever possible.</p> <p data-bo="286">I was also taught &quot;it&#x27;s a poor craftsman that blames their tools&quot;, which apparently means &quot;take responsibility for your fuckups&quot;, but, to young-me, definitely sounded more like &quot;you don&#x27;t deserve nice things&quot;.</p> <p data-bo="497">I was also taught from an early age that I was born a sinner, incapable of doing good by myself, and that all the earthly things were temptations, sent by the devil to corrupt me (further I guess?) but also temporary, and that I shouldn&#x27;t attach myself.</p> Cracking Electron apps open https://fasterthanli.me/articles/cracking-electron-apps-open 2023-07-03T16:30:00Z <p data-bo="148">I use the <a href="https://github.com/jgraph/drawio-desktop">draw.io desktop app</a> to make diagrams for my website. I run it on an actual desktop, like Windows or macOS, but the asset pipeline that converts <code>.drawio</code> files, to <code>.pdf</code>, to <code>.svg</code>, and then to <code>.svg</code> again (but smaller) runs on Linux.</p> <p data-bo="440">So I have a Rust program somewhere that opens headless chromium, and loads just the HTML&#x2F;JS&#x2F;CSS part of draw.io I need to render my diagrams, and then use Chromium&#x27;s &quot;print to PDF&quot; functionality to save a PDF.</p> The RustConf Keynote Fiasco, explained https://fasterthanli.me/articles/the-rustconf-keynote-fiasco-explained 2023-05-31T21:00:00Z <div class="disclosure paragraph-like"> <p data-bo="41"><strong>Disclaimer</strong>:</p> <p data-bo="172">At some point in this article, I discuss The Rust Foundation. I have received a $5000 grant from them in 2023 for making educational articles and videos about Rust.</p> <p data-bo="345">I have NOT signed any non-disclosure, non-disparagement, or any other sort of agreement that would prevent me from saying exactly how I feel about their track record.</p> </div><div class="disclosure paragraph-like"> <p data-bo="41"><strong>Disclaimer</strong>:</p> <p data-bo="537">I was part of the RustConf program committee in 2022, but not in 2023. More on that later.</p> </div> Rust: The wrong people are resigning https://fasterthanli.me/articles/rust-the-wrong-people-are-resigning 2023-05-28T17:04:00Z <p data-bo="114">(Note: this was originally posted <a href="https://gist.github.com/fasterthanlime/42da9378768aebef662dd26dddf04849">as a gist</a>)</p> <a id="reassuring-myself-about-rust" href="#reassuring-myself-about-rust" class="anchor"><h2>Reassuring myself about Rust</h2></a> <p data-bo="268">Up until recently, I was part of two private online discussion spaces where a bunch of Rust people hung out.</p> <p data-bo="378">So, whenever there was drama, like when the entire mod team resigned, or when a trademark draft got a lot of people seriously worried, or just recently when <a href="https://thephd.dev/i-am-no-longer-speaking-at-rustconf-2023">RustConf took back the keynote from ThePHD</a> then <a href="https://www.sophiajt.com/why-i-left-rust/">Sophia resigned over it</a> and , I had some place to go, to assess how serious things were this time around.</p> Extra credit https://fasterthanli.me/series/building-a-rust-service-with-nix/part-12 2023-03-05T07:30:12Z <p data-bo="104">We&#x27;ve achieved our goals already with this series: we have a web service written in Rust, built into a Docker image with nix, with a nice dev shell, that we can deploy to <a href="https://fly.io">fly.io</a>.</p> <p data-bo="302">But there&#x27;s always room for improvement, and so I wanted to talk about a few things we didn&#x27;t bother doing in the previous chapters.</p> <a id="making-clash-geoip-available-in-the-dev-shell" href="#making-clash-geoip-available-in-the-dev-shell" class="anchor"><h2>Making <code>clash-geoip</code> available in the dev shell</h2></a> <p data-bo="488">When we ran our app locally, we signed up for a MaxMindDB account, and had to download and unpack the &quot;Country&quot; Geolite2 database manually.</p> Generating a docker image with nix https://fasterthanli.me/series/building-a-rust-service-with-nix/part-11 2023-03-05T07:30:11Z <p data-bo="126">There it is. The final installment.</p> <p data-bo="163">Over the course of this series, we&#x27;ve built a <em>very useful</em> Rust web service that shows us colored ASCII art cats, and we&#x27;ve packaged it with docker, and deployed it to <a href="https://fly.io">https:&#x2F;&#x2F;fly.io</a>.</p> <p data-bo="351">We did all that without using <code>nix</code> at all, and then in the last few chapters, we&#x27;ve learned to use <code>nix</code>, and now it&#x27;s time to tell <code>docker build</code> goodbye, along with this whole-ass :</p> Making a dev shell with nix flakes https://fasterthanli.me/series/building-a-rust-service-with-nix/part-10 2023-03-05T07:30:10Z <p data-bo="117">In the previous chapter, we&#x27;ve made a nix &quot;dev shell&quot; that contained the fly.io command-line utility, &quot;flyctl&quot;.</p> <p data-bo="230">That said, that&#x27;s not how I want us to define a dev shell.</p> <p data-bo="290">Our current solution has issues. I don&#x27;t like that it has <code>import &lt;nixpkgs&gt;</code>. Which version of <code>nixpkgs</code> is that? The one you&#x27;re on? Who knows what that is.</p> <p data-bo="448">Also, we haven&#x27;t really seen a mechanism to use files from elsewhere.</p> Learning Nix from the bottom up https://fasterthanli.me/series/building-a-rust-service-with-nix/part-9 2023-03-05T07:30:09Z <p data-bo="114">Remember the snapshot we made allll the way back in <a href="part-1">Part 1</a>? Now&#x27;s the time to use it.</p> <p data-bo="211">Well, make sure you&#x27;ve committed and pushed all your changes, but when you&#x27;re ready, let&#x27;s go back in time to before we installed anything catscii-specific in our VM.</p> <p data-bo="379">This should emulate the experience of a colleague onboarding onto the project well enough!</p> <p data-bo="471">(I didn&#x27;t actually use VirtualBox&#x27;s snapshot feature for this, I actually set up a Ubuntu 22.10 VM on another computer entirely, but the effect should be much the same).</p> Doing geo-location and keeping analytics https://fasterthanli.me/series/building-a-rust-service-with-nix/part-8 2023-03-05T07:30:08Z <p data-bo="156">I sold you on some additional functionality for <code>catscii</code> last chapter, and we got caught up in private registry &#x2F; docker shenanigans, so, now, let&#x27;s resume web development as promised.</p> <a id="adding-geolocation" href="#adding-geolocation" class="anchor"><h2>Adding geolocation</h2></a> <p data-bo="366">We kinda left the <code>locat</code> crate stubby, it doesn&#x27;t <em>actually</em> do any IP to location lookups. It doesn&#x27;t even have a dependency on a crate that <em>can</em> do that.</p> <p data-bo="525">So, let&#x27;s do that. We&#x27;ll use the crate, which can read the MaxMind DB format, like GeoIP2 and GeoLite2:</p> Using the Shipyard private crate registry with Docker https://fasterthanli.me/series/building-a-rust-service-with-nix/part-7 2023-03-05T07:30:07Z <div class="dialog bear"> <div class="dialog-head" title="Cool bear says:"> <picture> <source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/img/reimena/cool-bear-neutral~318815444a238722.jxl"> <source type="image/avif" srcset="https://cdn.fasterthanli.me/content/img/reimena/cool-bear-neutral~855ba1f506e3aa13.avif"> <source type="image/webp" srcset="https://cdn.fasterthanli.me/content/img/reimena/cool-bear-neutral~1cd56ba16f658405.webp"> <img src="https://cdn.fasterthanli.me/content/img/reimena/cool-bear-neutral~318815444a238722.jxl" class="bear" width="42" height="42" alt="Cool bear"> </picture> </div> <div class="dialog-text markup-container"> <p data-bo="179">Wait wait wait, so we&#x27;re not talking about nix yet?</p> </div> </div><p data-bo="232">Well, no! The service we have is pretty simple, and I want to complicate things a bit, to show how things would work in both the Dockerfile and the nix scenario.</p> <p data-bo="395">And because I don&#x27;t like contrived examples, we&#x27;re going to do something somewhat real-world: we&#x27;re going to geo-locate visitors, and track how many visits we get from each country.</p> Deploying catscii to fly.io https://fasterthanli.me/series/building-a-rust-service-with-nix/part-6 2023-03-05T07:30:06Z <div class="disclosure paragraph-like"> <p data-bo="41"><strong>Disclaimer</strong>:</p> <p data-bo="153">Because I used to work for fly.io, I still benefit from an employee discount at the time of this writing: I don&#x27;t have to pay for anything deployed there for now.</p> <p data-bo="324">fly.io is still <a href="/donate">sponsoring me</a> for developing <a href="https://github.com/hapsoc/hring">hring</a>, but this isn&#x27;t a sponsored post. It&#x27;s just a good fit for what we&#x27;re doing here, with a generous free tier.</p> </div><p data-bo="535">In the <a href="part-5">previous chapter</a>, we&#x27;ve written a to build the service inside Docker. The result is a container image that can be pushed to production!</p> Writing a Dockerfile for catscii https://fasterthanli.me/series/building-a-rust-service-with-nix/part-5 2023-03-05T07:30:05Z <p data-bo="127">Now that our service is production-ready, it&#x27;s time to deploy it somewhere.</p> <p data-bo="204">There&#x27;s a lot of ways to approach this: what we are going to do, though, is build a docker image. Or, I should say, an <a href="https://github.com/opencontainers/image-spec">OCI image</a>.</p> <p data-bo="383">This is still a series about Nix, but again: because the best way to see the benefits of Nix is to do it <em>without</em> Nix first, we&#x27;ll use only Docker&#x27;s tooling to build the image.</p> <a id="installing-docker-on-ubuntu" href="#installing-docker-on-ubuntu" class="anchor"><h2>Installing Docker on Ubuntu</h2></a> Serving ASCII cats over HTTP https://fasterthanli.me/series/building-a-rust-service-with-nix/part-4 2023-03-05T07:30:04Z <p data-bo="146">Our <code>catscii</code> program does everything we want it to do, except that it&#x27;s a command-line application rather than a web server. Let&#x27;s fix that.</p> <a id="enter-axum" href="#enter-axum" class="anchor"><h2>Enter <code>axum</code></h2></a> <p data-bo="306">The documentation for the <a href="https://crates.io/crates/axum">axum</a> crate tells us how to make a basic web server, and we honestly don&#x27;t need much more than that.</p> <p data-bo="466">So let&#x27;s add axum:</p> <code class="code-block has-language-tag" translate="no" data-lang="shell""><label class="language-tag" title="Shell session"></label><pre class="scroll-wrapper">amos@miles:~/catscii$ cargo add [email protected] Updating crates.io index Adding axum =0.6 to dependencies. Features: + form + http1 + json + matched-path + original-uri + query + tokio + tower-log - __private_docs - headers - http2 - macros - multipart - w </pre></code> Printing ASCII cats to the terminal https://fasterthanli.me/series/building-a-rust-service-with-nix/part-3 2023-03-05T07:30:03Z <p data-bo="131">Now that our development environment is all set up, let&#x27;s make something useful!</p> <a id="creating-the-catscii-crate" href="#creating-the-catscii-crate" class="anchor"><h2>Creating the <code>catscii</code> crate</h2></a> <p data-bo="246">From a VS Code window connected to our VM (as we <a href="part-2">just set up</a>), let&#x27;s make a new Rust project:</p> <code class="code-block has-language-tag" translate="no" data-lang="shell""><label class="language-tag" title="Shell session"></label><pre class="scroll-wrapper">amos@miles:~$ cargo new catscii Created binary (application) `catscii` package </pre></code><p data-bo="449">And open it in a new VSCode window:</p> <code class="code-block has-language-tag" translate="no" data-lang="shell""><label class="language-tag" title="Shell session"></label><pre class="scroll-wrapper">amos@miles:~$ code catscii </pre></code><p data-bo="527">Even though we&#x27;re running this &quot;code&quot; command in the VM guest, VSCode set up enough plumbing that it communicates back to the host, telling it to open another VSCode window, connected to the same SSH remote, in the right folder.</p> Developing over SSH https://fasterthanli.me/series/building-a-rust-service-with-nix/part-2 2023-03-05T07:30:02Z <p data-bo="113">With <a href="part-1">the previous part</a>&#x27;s VM still running, let&#x27;s try connecting to our machine over SSH.</p> <a id="network-addresses-loopback-and-ip-nets" href="#network-addresses-loopback-and-ip-nets" class="anchor"><h2>Network addresses, loopback and IP nets</h2></a> <p data-bo="257">Normally, to connect to a machine, you&#x27;d find its IP address. On Linux, a decade ago, you would&#x27;ve used <code>ifconfig</code>. Nowadays you can use <code>ip addr</code>:</p> <p data-bo="406"><picture><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/part-2/assets/ip-addr~91ed63cb9a392561.jxl"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/part-2/assets/ip-addr~e5c07383ef672e97.avif"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/part-2/assets/ip-addr~dfb6487be8cd875d.webp"><img src="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/part-2/assets/ip-addr~91ed63cb9a392561.jxl" loading="lazy" width="800" height="600" title="The ip addr command output, run in VirtualBox" alt="The ip addr command output, run in VirtualBox"></picture></p> <p data-bo="476">The loopback interface (<code>lo</code>) is local, so it&#x27;s not useful to reach the box from the outside: you can see it can be accessed over IPv4 at address 127.0.0.1 but not just! What we&#x27;re reading here is 127.0.0.1&#x2F;8, which corresponds to the range </p> Setting up a local Ubuntu Server VM https://fasterthanli.me/series/building-a-rust-service-with-nix/part-1 2023-03-05T07:30:01Z <p data-bo="136">The first step to using Nix to build Rust is to do so <em>without</em> Nix, so that when we finally do, we can feel the difference.</p> <p data-bo="262">There&#x27;s many ways to go about this: everyone has their favorite code editor, base Linux distribution (there&#x27;s even a <a href="https://nixos.org/">NixOS</a> distribution, which I won&#x27;t cover). Some folks like to develop on macOS first, and <em>then</em> build for Linux.</p> <p data-bo="515">Y&#x27;all are all valid, but for this series, we&#x27;re going to very specifically do what I before nix, and what I&#x27;m doing now that I&#x27;ve embraced my 30s and become &quot;a nix person&quot;, and we&#x27;ll evaluate the ups and downsides of both approaches.</p> The bottom emoji breaks rust-analyzer https://fasterthanli.me/articles/the-bottom-emoji-breaks-rust-analyzer 2023-02-13T14:20:00Z <p data-bo="131">Some bugs are merely fun. Others are simply delicious!</p> <p data-bo="187">Today&#x27;s pick is the latter.</p> <a id="reproducing-the-issue-part-1" href="#reproducing-the-issue-part-1" class="anchor"><h2>Reproducing the issue, part 1</h2></a> <p data-bo="250">(It may be tempting to skip that section, but reproducing an issue is an important part of figuring it out, so.)</p> <p data-bo="364">I&#x27;ve never used Emacs before, so let&#x27;s install it. I do most of my computing on an era-appropriate Ubuntu, today it&#x27;s Ubuntu 22.10, so I just need to:</p> <code class="code-block has-language-tag" translate="no" data-lang="shell""><label class="language-tag" title="Shell session"></label><pre class="scroll-wrapper">$ sudo apt install emacs-nox </pre></code> Day 18 (Advent of Code 2022) https://fasterthanli.me/series/advent-of-code-2022/part-18 2023-01-12T14:00:00Z <p data-bo="139">This time around, we&#x27;re porting a solution from C++ to Rust and seeing how it feels, how it performs, and what we can learn about both languages by doing that.</p> <p data-bo="300">See <a href="part-17">Day 17</a> for the rationale re: porting solutions rather than writing my own from scratch. TL;DR is: it&#x27;s better than nothing, and we can still focus about learning Rust rather than spending entire days fighting off-by-one errors.</p> <p data-bo="544">The research for this article was done live on stream, I&#x27;m not going to cover everything in the write-up, so check it out if you want the full experience:</p> Twitch fell behind https://fasterthanli.me/articles/twitch-fell-behind 2023-01-12T13:00:00Z <p data-bo="125">So you want to do live streams. Are you sure? Okay. Let&#x27;s talk about it.</p> <a id="let-s-talk-numbers" href="#let-s-talk-numbers" class="anchor"><h2>Let&#x27;s talk numbers</h2></a> <p data-bo="222">Being a &quot;content creator&quot; (sorry for those who hate that term) <em>is</em> a job, for sure, and many people do it, successfully, full-time, they pay rent with it etc.</p> <p data-bo="383">Platforms like Twitch &amp; YouTube would have you think that, if you put in enough effort, you can grow your channel from nothing to 🎉 profitable ✨ in just a few short years.</p> Day 17 (Advent of Code 2022) https://fasterthanli.me/series/advent-of-code-2022/part-17 2023-01-11T15:00:00Z <p data-bo="142">Advent of Code gets harder and harder, and I&#x27;m not getting any smarter. Or any more free time. So, in order to close out this series anyway, I&#x27;m going to try and port other people&#x27;s solutions from &quot;language X&quot; to Rust. That way, they already figured out the hard stuff, and we can just focus on the Rust bits!</p> <p data-bo="453">Sounds good? Good. Let&#x27;s proceed.</p> <p data-bo="488">The research for this article was done live on and , if you&#x27;d rather watch me go through it step by step, you can watch the VOD below:</p> Day 16 (Advent of Code 2022) https://fasterthanli.me/series/advent-of-code-2022/part-16 2022-12-29T15:00:00Z <p data-bo="131">Let&#x27;s tackle the <a href="https://adventofcode.com/2022/day/16">day 16 puzzle</a>!</p> <a id="parsing" href="#parsing" class="anchor"><h2>Parsing</h2></a> <p data-bo="216">The input looks like this:</p> <code class="code-block" translate="no" data-lang="""><pre class="scroll-wrapper">Valve AA has flow rate=0; tunnels lead to valves DD, II, BB Valve BB has flow rate=13; tunnels lead to valves CC, AA Valve CC has flow rate=2; tunnels lead to valves DD, BB Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE Valve EE has flow rate=3; tunnels lead to valves FF, DD Valve FF has flow rate=0; tunnels lead to valves EE, GG Valve GG has flow rate=0; tunnels lead to valves FF, HH Valve HH has flow rate=22; tunnel leads to valve GG Valve II has flow rate=0; tunnels lead to valves AA, JJ Valve JJ has flow rate=21; tunnel leads to valve II </pre></code>