<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title></title>
    <link rel="self" type="application/atom+xml" href="https://blog.asonix.dog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.asonix.dog"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-20T00:00:00+00:00</updated>
    <id>https://blog.asonix.dog/atom.xml</id>
    <entry xml:lang="en">
        <title>Cross Compiling Rust with Nix</title>
        <published>2026-03-20T00:00:00+00:00</published>
        <updated>2026-03-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.asonix.dog/005-cross-compiling-rust-with-nix/"/>
        <id>https://blog.asonix.dog/005-cross-compiling-rust-with-nix/</id>
        
        <content type="html" xml:base="https://blog.asonix.dog/005-cross-compiling-rust-with-nix/">&lt;p&gt;Recently I got to thinking about cross compiling rust again because I need to produce binaries for
different platforms for my project &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;asonix&#x2F;pict-rs&quot;&gt;pict-rs&lt;&#x2F;a&gt;. I never quite
liked how I made it work in CI after migrating from drone to forgejo actions (see my first blog post
on here for forgejo actions hate), so I&#x27;m always interested in ways to make builing my binaries
easier.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;existing-solutions&quot;&gt;Existing Solutions&lt;&#x2F;h2&gt;
&lt;p&gt;Unfortunately, cross compiling with Nix has been complicated. Sure, there&#x27;s a bunch of packages in
&lt;code&gt;pkgs.pkgsCross.*&lt;&#x2F;code&gt;, but how do you even use any of them? And why can&#x27;t I just do
&lt;code&gt;cargo build --target=some-other-triple&lt;&#x2F;code&gt;? In other environments, I would simply use rustup and
install the right toolchain, set a few environment variables, and produce some statically linked
musl binaries. In my current CI setup, I use &lt;code&gt;cargo zigbuild&lt;&#x2F;code&gt; from within a debian environment to
compile and link against the musl libc for x86_64, aarch64, and armv7, and that&#x27;s the simplest I&#x27;ve
managed to get things.&lt;&#x2F;p&gt;
&lt;p&gt;Looking online for documentation on rust programs with nix, there&#x27;s always references to third party
overlays like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nix-community&#x2F;fenix&quot;&gt;fenix&lt;&#x2F;a&gt;, which I&#x27;m sure are very good, but I
don&#x27;t want to use. I want my programs to be easily packaged for Nix and other distributions. The
more I complicate my build process, the more work distro maintainers will need to do to keep up with
it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;derivations&quot;&gt;Derivations&lt;&#x2F;h2&gt;
&lt;p&gt;In my pict-rs repo, I maintain a simple pict-rs.nix derivation, which is copied almost verbatim from
the NixOS pict-rs package. I do this so that I can run &lt;code&gt;nix build&lt;&#x2F;code&gt; every now and then to see if the
build process needs changing, and to provide an example to packagers that includes a clean
dependency list and build process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naively-crosspackagesing&quot;&gt;Naively crossPackagesing&lt;&#x2F;h2&gt;
&lt;p&gt;Since I have a neat derivation for building pict-rs already, and nix includes a &lt;code&gt;callPackage&lt;&#x2F;code&gt;
helper, and supports the targets I care about in &lt;code&gt;pkgs.pkgsCross&lt;&#x2F;code&gt;, would it be possible to just use
my existing derivation and cross-compile natively in nix? Yes, kind of, and no.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  crossPackages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; import&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; nixpkgs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    inherit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt; system&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;    crossSystem&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;aarch64-linux&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  packages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;    pict-rs-arm64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; crossPackages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;callPackage&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;pict-rs.nix&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works! Except it produces an aarch64 binary linked dynamically against glibc, which is not what
I want for distributing binaries that should Run Anywhere. I need resulting binaries to be statically
linked. When looking into this, I found nix provides a &lt;code&gt;pkgsMusl&lt;&#x2F;code&gt; package set, which is conveniently
easy to try!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  packages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;    pict-rs-arm64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; crossPackages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgsMusl&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;callPackage&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;pict-rs.nix&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this works too! Except...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ file result&#x2F;bin&#x2F;.pict-rs-wrapped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&#x2F;bin&#x2F;.pict-rs-wrapped: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter &#x2F;nix&#x2F;store&#x2F;rpqv8iricasr9hbmp1xfwsfhy2q1k9dk-musl-aarch64-unknown-linux-musl-1.2.5&#x2F;lib&#x2F;ld-musl-aarch64.so.1, not stripped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What do you mean dynamically linked? I built with musl and rust statically links as much as it
can! Well, rust here is coming from nix, and nix configured it to dynamically link, so this also is
not what I want.&lt;&#x2F;p&gt;
&lt;p&gt;But wait! What&#x27;s that I see in the &lt;code&gt;nix repl&lt;&#x2F;code&gt;? &lt;code&gt;pkgsStatic&lt;&#x2F;code&gt;? Is this what I have been looking for the whole-&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;collect2: error: ld returned 1 exit status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I see. Well that&#x27;s unfortunate. I guess I can&#x27;t cross compile pict-rs that easily with nix, then.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-it-s-actually-easy&quot;&gt;But it&#x27;s actually easy&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s have a bit of a think on that linking error we got. What failed to link? it was
&lt;code&gt;perl-static-aarch64-unknown-linux-musl&lt;&#x2F;code&gt;. Do we care about perl? why is it even here? Well it&#x27;s a
dependency of exiftool, which we need at runtime for pict-rs to function, but not at build time. And
we don&#x27;t need ffmpeg or imagemagick either! What if instead of calling &lt;code&gt;callPackage&lt;&#x2F;code&gt; on the normal
pict-rs derivation, I called it on a custom derivation with no runtime dependencies listed?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  pict-rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pkgs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgsCross&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;aarch64-multiplatform&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgsStatic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;callPackage&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;pict-rs-unwrapped.nix&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ file result&#x2F;bin&#x2F;pict-rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&#x2F;bin&#x2F;pict-rs: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, not stripped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oh!&lt;&#x2F;p&gt;
&lt;p&gt;Well that&#x27;s good. What about armv7? I still want to support that even though it&#x27;s old and SBCs these
days are aarch64. What if someone is running a Rasbperry Pi 2 Model B?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  pict-rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pkgs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgsCross&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;armv7-hf-multiplatform&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgsStatic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;callPackage&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;pict-rs-unwrapped.nix&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ file result&#x2F;bin&#x2F;pict-rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;result&#x2F;bin&#x2F;pict-rs: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oh! That was easy. But... it took so long. These static builds&#x27; tools aren&#x27;t cached in hydra, which
means I had to compile gcc and rustc on my computer before I could even start compiling pict-rs. If
I wanted to do this in CI, I&#x27;d need my own nix cache to avoid doing that a lot. Oh well.&lt;&#x2F;p&gt;
&lt;p&gt;I added these packages to my flake anyway, slightly modified to make extending it with other
platforms easier.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;let&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  targets&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;      triple&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;x86_64-unknown-linux-musl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;      name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;amd64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;      triple&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;aarch64-unknown-linux-musl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;      name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;arm64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;      triple&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;armv7l-unknown-linux-musleabihf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;      name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;armv7l&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;  packages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    builtins&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;foldl&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;      acc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity&quot;&gt;      {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; triple&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-entity&quot;&gt; }&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      let&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;        crossPkgs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; import&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; nixpkgs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;          inherit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt; system&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;          crossSystem&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt;config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; triple&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;      acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pict-rs-&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; crossPkgs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgsStatic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;callPackage&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;pict-rs-unwrapped.nix&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;          inherit&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;pkgs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;darwin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;apple_sdk&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;frameworks&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name&quot;&gt; Security&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; targets&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Configuring crossPkgs with &lt;code&gt;crossSystem.config&lt;&#x2F;code&gt; is notable, since I didn&#x27;t realize that was possible
until I saw another blog post about cross compiling rust with nix. I came to a different conclusion
than they did about the ease of compiling, though. Using derivations and callPackage definitely
simplifies the build, and adding other targets just means extending the &lt;code&gt;targets&lt;&#x2F;code&gt; list.&lt;&#x2F;p&gt;
&lt;p&gt;Since I don&#x27;t want to set up a nix cache for myself, I don&#x27;t think I&#x27;ll switch my CI to use nix to
build these binaries, but it&#x27;s good to know that it&#x27;s possible and not even difficult.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Moving</title>
        <published>2024-07-20T00:00:00+00:00</published>
        <updated>2024-07-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.asonix.dog/004-moving/"/>
        <id>https://blog.asonix.dog/004-moving/</id>
        
        <content type="html" xml:base="https://blog.asonix.dog/004-moving/">&lt;p&gt;I will be moving in two weeks.&lt;&#x2F;p&gt;
&lt;p&gt;Because of this, all asonix.dog services will be OFFLINE for somewhere between a few hours and a few
days starting Friday August 2nd at 1pm UTC.&lt;&#x2F;p&gt;
&lt;p&gt;If you need to access source code for anything I work on, the important stuff is mirrored on
codeberg: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;asonix&quot;&gt;https:&#x2F;&#x2F;codeberg.org&#x2F;asonix&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I will do my best to bring everything back online in a timely manner but we&#x27;ll need to see how it
actually goes when we get there.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Help! My function is Crimson!</title>
        <published>2024-02-15T00:00:00+00:00</published>
        <updated>2024-02-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.asonix.dog/003-the-crimson-chin/"/>
        <id>https://blog.asonix.dog/003-the-crimson-chin/</id>
        
        <content type="html" xml:base="https://blog.asonix.dog/003-the-crimson-chin/">&lt;p&gt;This post will hopefully be shorter than the last two. I just wanted to dig into the fourth function
color brought up in
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;JarredAllen&#x2F;6cd2fd5faead573d1120a96135ed3346&quot;&gt;Which &quot;Red&quot; is your function?&lt;&#x2F;a&gt;
I&#x27;m not going to get into the details of function coloring here. If you want to know you can read
the linked article, and the articles the linked article links.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: If you want to talk about io-uring or io-ring or IOCP that&#x27;s an entire other discussion that
plays into this problem but will not be covered here.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;how-do-you-do-io&quot;&gt;How do you do IO?&lt;&#x2F;h2&gt;
&lt;p&gt;This is really the crux of the issue. How do you do IO. In the standard library, you can have a
TcpStream and issue a &lt;code&gt;.read()&lt;&#x2F;code&gt; on it and get the bytes. This works by passing the TcpStream&#x27;s File
Descriptor to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;read.2.html&quot;&gt;&lt;code&gt;read&lt;&#x2F;code&gt; syscall&lt;&#x2F;a&gt;. Calling
this function can have a couple results:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Bytes were read from the provided descriptor and placed into the provided buffer. The function&#x27;s
return value indicates how many bytes were read.&lt;&#x2F;li&gt;
&lt;li&gt;No bytes were read because there are no more bytes to read. No bytes are placed into the buffer
and the function&#x27;s return value is 0. This indicates that the &lt;code&gt;read&lt;&#x2F;code&gt; call should not be retried.&lt;&#x2F;li&gt;
&lt;li&gt;No bytes were read because some sort of error occured. No bytes are placed into the buffer and
the function&#x27;s return value is less than 0, each possible sub-zero value corresponds with a
specific error.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is all well and good, but it doesn&#x27;t work well in contexts where we aren&#x27;t supposed to &lt;code&gt;block&lt;&#x2F;code&gt;.
Consider the case where we&#x27;re talking with a very slow computer, and it is sending us bytes, but we
don&#x27;t receive them in a reasonable timeframe. Using the &lt;code&gt;read&lt;&#x2F;code&gt; syscall as-is doesn&#x27;t allow our
program to do anything else while we&#x27;re waiting on the slow computer.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily there&#x27;s a very common workaround for this specific issue. We can put our TcpStream in
non-blocking mode, which will slightly alter the behavior of the &lt;code&gt;read&lt;&#x2F;code&gt; syscall. Now instead of
waiting for bytes to put into the provided buffer, if there are no bytes available the &lt;code&gt;read&lt;&#x2F;code&gt; call
will return immediately with a new error value. Our program can notice this new error value and
realize that although we didn&#x27;t read anything this time, in the future we will be able to read
something.&lt;&#x2F;p&gt;
&lt;p&gt;But how will we know when to try reading again? That is the core problem that creates our Crimson
functions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-will-they-know-they-re-gonna-know&quot;&gt;How will they know? (They&#x27;re gonna know)&lt;&#x2F;h2&gt;
&lt;p&gt;In Rust there&#x27;s a number of async runtimes that you can choose from. tokio is by and large the one
people will use or tell you to use, but there&#x27;s also smol, async-std, embassy, glommio, monoio,
actix-rt, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;safe-async&#x2F;jive&quot;&gt;jive (I wrote this one)&lt;&#x2F;a&gt;, and I&#x27;m sure others.
The primary motivating factor for having multiple runtimes like this is to play with different ideas
of IO. I said up front that I&#x27;m not going to talk about completion-based IO, embassy is another
special case, actix-rt is just tokio with extra steps, and smol and async-std are basically the same
runtime, so let&#x27;s pretend for now that the only runtimes that exist are tokio and async-std.&lt;&#x2F;p&gt;
&lt;p&gt;The real distinction between tokio and async-std is how they attempt to figure out &lt;em&gt;when&lt;&#x2F;em&gt; to try
reading more bytes. In both cases, after failing to read bytes from the TcpStream, the runtime will
register the TcpStream&#x27;s file descriptor with an event mechanism. This mechanism is backed by a
blocking IO operation, just like a blocking &lt;code&gt;read&lt;&#x2F;code&gt;, but unlike a blocking &lt;code&gt;read&lt;&#x2F;code&gt;, the event
mechanism does not itself read any bytes, and it is capable of waiting for available bytes for many
file descriptors simultaneously. This means that if your program has 30 TcpStreams, you can block
waiting for any one of them to become available for reading on a single thread. Since this operation
does block, tokio and async-std need to strike a balance between waiting for events on these
registered file descriptors, and making progress on other asynchronous tasks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-that-s-why-my-crimson-functions-explode&quot;&gt;And that&#x27;s why my crimson functions explode?&lt;&#x2F;h2&gt;
&lt;p&gt;Yeah basically. tokio&#x27;s TcpStream type knows how to register itself with tokio&#x27;s event mechanism,
and is designed to play with tokio&#x27;s scheduling. Underneath, the bytes are still read with the
&lt;code&gt;read&lt;&#x2F;code&gt; syscall we talked about earlier, but all the surrounding bits about deciding when to read
make it unique.&lt;&#x2F;p&gt;
&lt;p&gt;async-std&#x27;s TcpStream type is the same thing. It knows how to register itself with async-std&#x27;s event
mechanism, and plays &lt;em&gt;as nicely as it can*&lt;&#x2F;em&gt; with async-std&#x27;s scheduling. It really comes down to
that registration step for the difference between these two runtimes. It is feasible that the Future
trait&#x27;s &lt;code&gt;Context&lt;&#x2F;code&gt; argument could be extended with a method such as &lt;code&gt;.register(fd: &amp;amp;BorrowedFd&amp;lt;&#x27;_&amp;gt;)&lt;&#x2F;code&gt;.
This could potentially allow any type with access to a File Descriptor to register with any
runtime&#x27;s event mechanism. But it&#x27;s not enough to handle every scenario.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;*tokio has a cooperation mechanism that its TcpStream integrates with to reduce task starvation
and async-std does not.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;why-not&quot;&gt;Why not?&lt;&#x2F;h2&gt;
&lt;p&gt;Well for one, not every runtime has an event mechanism like async-std and tokio do. I left out
runtimes using completion-based IO because they work in an entirely different way. I left out
embassy because it&#x27;s designed for microcontrollers and doesn&#x27;t have access to an operating system
that could provide &lt;code&gt;read&lt;&#x2F;code&gt;. Building an abstraction around an event mechanism and file descriptors
leaves out other runtime implementations that don&#x27;t include one or both of these concepts. These
problems are why we don&#x27;t have a unified API for dealing with runtimes outside of the Future trait.
Unification is hard. It might not be possible. But there&#x27;s a bunch of smart folks thinking about it,
so maybe things will get better.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What is Public?</title>
        <published>2024-02-13T00:00:00+00:00</published>
        <updated>2024-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.asonix.dog/002-what-is-public/"/>
        <id>https://blog.asonix.dog/002-what-is-public/</id>
        
        <content type="html" xml:base="https://blog.asonix.dog/002-what-is-public/">&lt;blockquote&gt;
&lt;p&gt;Foreword: In this post I mention Mastodon by name a couple times because that is the primary
software I use to access the ActivityPub network. Please do not see this as a conflation of
Mastodon with &quot;The Fedi.&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yesterday I became aware of a project that aims to bridge ActivityPub and ATProto together by acting
as a traditional ActivityPub server, as well as an ATProto PDS. This is a reasonable approach from a
technical perspective. It will behave as expected of a native implementation on each side, while
proxying users and posts through.&lt;&#x2F;p&gt;
&lt;p&gt;But there&#x27;s a disconnect between what Public means on each side of the bridge, and I&#x27;d like to take
some time to dig into what that word means. While this discussion will get somewhat technical, there
are &lt;em&gt;reasons&lt;&#x2F;em&gt; for the distinction after all, I&#x27;m not going to go in depth into either protocol.
We&#x27;ll try to stick to a higher level view of each network.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;atproto&quot;&gt;ATProto&lt;&#x2F;h2&gt;
&lt;p&gt;What the heck is ATProto? It&#x27;s likely that more folks on Mastodon know about ATProto than folks on
Bluesky, but there&#x27;s certainly folks on both platforms that don&#x27;t know about ATProto. ATProto is the
federation protocol that Bluesky will be implementing eventually. It will enable Bluesky to exist
within a wider network of services that operate independently of eachother, but still enable ease of
discovery and &quot;seamless integration.&quot; ATProto is the reason why everything on Bluesky is public. The
protocol works by giving every participating service full access to everything a user does,
including Posts, Follows, Followers, Blocks, Likes, etc.&lt;&#x2F;p&gt;
&lt;p&gt;ATProto is designed to be maximally discoverable. This works by having large central services that
are responsible for collecting the data from all known users, and those central services provide
mechanisms to subscribe to all the user data they know about. &quot;The Firehose.&quot; This model hasn&#x27;t been
deployed widely in production because Bluesky itself has not enabled ATProto, and so there&#x27;s no
concrete data for how this model will pan out.&lt;&#x2F;p&gt;
&lt;p&gt;For those of you on Bluesky surprised by the idea that Bluesky might federate, I want you to know
this was always the plan. From when Jack first mentioned Bluesky when he still owned Twitter,
federation was always the plan.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;activitypub&quot;&gt;ActivityPub&lt;&#x2F;h2&gt;
&lt;p&gt;ActivityPub has been around for some years now. It is famously the protocol that Mastodon uses to
federate. In ActivityPub, each participating server is responsible for making their posts and users
known to the wider network. There&#x27;s no central discovery or publishing service like in ATProto,
although &lt;code&gt;relays&lt;&#x2F;code&gt; exist to fill a similar niche. In ActivityPub, there&#x27;s no prescribed mechanism to
denote what is public and what is not public, so implementations began relying on convention to
signal to each other how public a given post should be. In Mastodon&#x27;s model there are four varying
levels of &quot;public-ness&quot; that posts can have.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Direct - This post is only visible to mentioned users&lt;&#x2F;li&gt;
&lt;li&gt;Followers Only - This post is only visible to mentioned users, and users that follow the poster&lt;&#x2F;li&gt;
&lt;li&gt;Unlisted - This post is visible to anyone, but is left out of discovery mechanisms&lt;&#x2F;li&gt;
&lt;li&gt;Public - This post is visible to anyone, and is included in discovery mechanisms&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In order for this model to work, all participating services must agree on these privacy levels
meaning what they do. It is possible for a malicious or malfunctioning ActivityPub implementation to
improperly treat a post as more public than it was intended to be, resulting in reach beyond the
intended audience. In order for this to happen, however, the post must first &lt;em&gt;reach&lt;&#x2F;em&gt; the bad
implementation for it to be rebroadcast. Direct messages are not likely to be made public, since it
would require one of the parties in the thread to exist on a malicious server. I assume that most
Direct messages happen between parties that know each other and are using compliant impelementations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;relays&quot;&gt;Relays&lt;&#x2F;h3&gt;
&lt;p&gt;As I mentioned above, ActivityPub has a concept of &quot;relays.&quot; These are opt-in mechanisms to improve
discoverability of posts. ActivityPub servers can &quot;subscribe&quot; to relays of their choosing, and when
they do so, they send all future public posts they host to the relay. The relay in turn broadcasts
all those posts to the other subscribed servers. This provides a similar function to the central
services in ATProto, but in ActivityPub there is no default relay, and relays are generally operated
at small scales. They also don&#x27;t generally have a &quot;public feed&quot; that anyone can subscribe to,
although that&#x27;s not a huge barrier to entry for a sufficiently motivated programmer.&lt;&#x2F;p&gt;
&lt;p&gt;I personally maintain an ActivityPub relay implementation called
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;asonix&#x2F;relay&quot;&gt;AodeRelay&lt;&#x2F;a&gt;, and I host an
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;relay.asonix.dog&quot;&gt;invite-only version of it&lt;&#x2F;a&gt; for furry and adjacent servers to share their
posts to each other. In order for a server to join my relay, that server&#x27;s administrator needs to
contact me to request permission to join. I haven&#x27;t yet said no to a request, but just having that
option is nice. As a relay administrator, I am responsible for the content my relay is forwarding. I
want my relay to remain useful to the servers that subscribe to it, and if my relay starts putting
unwanted content into people&#x27;s feeds, it is no longer useful.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-what-is-public&quot;&gt;So What is Public?&lt;&#x2F;h2&gt;
&lt;p&gt;This is where we really get to compare the two models. Public in ATProto is everything. Every post.
Every Like. Every Follow. Every participating ATProto service can be made aware of any activity on
ATProto in real time. All user history is publicly available to anyone who looks. In ActivityPub
only Some Things are public, and even then, there&#x27;s far less reach for things that are public.
There&#x27;s no mechanism to subscribe to All Public Things, and often times even public things are only
shared between one or two participating servers. Public means two different things in these two
different networks.&lt;&#x2F;p&gt;
&lt;p&gt;I have mused in the past about direct ATProto integration in Mastodon. I think it&#x27;s possible, and I
think it&#x27;s even a good idea to pursue. It would give mastodon users more reach &lt;em&gt;if they want it.&lt;&#x2F;em&gt; My
prefered implementation of this would be the introduction of a fifth privacy setting.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Direct - This post is only visible to mentioned users&lt;&#x2F;li&gt;
&lt;li&gt;Followers Only - This post is only visible to mentioned users, and users that follow the poster&lt;&#x2F;li&gt;
&lt;li&gt;Unlisted - This post is visible to anyone, but is left out of discovery mechanisms&lt;&#x2F;li&gt;
&lt;li&gt;Public - This post is visible to anyone, and is included in discovery mechanisms&lt;&#x2F;li&gt;
&lt;li&gt;Super Public - This post is visible to anyone, and is included in discovery mechanisms, and is
actively broadcast to literally anyone who happens to be listening on ATProto&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Super Public is inherently a superset if Public. Not only can anyone see the post, and not only is
the post used to help users find each other and sent to relays and able to be forwarded farther in
the network, but it is sent directly to every single service that is listening to ATProto&#x27;s
firehose. It greatly improves reach over just the Public option that Mastodon currently has, but
that comes at the cost of privacy.&lt;&#x2F;p&gt;
&lt;p&gt;As it stands, Public posts on Mastodon (and other compliant ActivityPub impelementations) are still
somewhat private. Sure anyone &lt;em&gt;can&lt;&#x2F;em&gt; see them, but realistically who will? Someone happening to check
the federated timeline on one of the 100 servers subscribed to my relay when I make the post? My
followers? If nobody boosts my public post then the total number of views it might get is probably
20. And certainly 3rd parties, who scrape and aggregate posts to gain more insight into users, are
far less likely to see even my public post on ActivityPub than any given post on ATProto.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-you-don-t-like-the-bridge&quot;&gt;And you don&#x27;t like the bridge?&lt;&#x2F;h2&gt;
&lt;p&gt;No I don&#x27;t like the bridge. I&#x27;ve already requested that my accounts be opted out, and provided a
suggestion for a middle ground that enables anyone to opt in at any time for any specific post. From
the ATProto side, bridging posts into ActivityPub comes at no additional disadvantage. All their
data is public already, and trivially accessible to anyone who cares to look. But from the
ActivityPub side, the bridge is introducing a new level of discoverability to a network that thusfar
hasn&#x27;t had such a concept.&lt;&#x2F;p&gt;
&lt;p&gt;I think it&#x27;s critically important that developers of bridge software like this &lt;em&gt;recognize&lt;&#x2F;em&gt; that what
they are doing is novel. Developers of bridge software need to acknowledge that they are changing
the experience of ActivityPub users by creating these bridges, even if nobody ever interacts with
them across the bridge. ActivityPub users need to understand as well that their reasonable
expectations of privacy can be violated at any moment by implementations such as this ATProto bridge
and the folks who would build and deploy such services.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;extra-thoughts-in-no-particular-order&quot;&gt;Extra Thoughts in no particular order&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;I tried not to make this post about Bluesky and Mastodon themselves, but to talk specifically
about the nature of the protocols involved.&lt;&#x2F;li&gt;
&lt;li&gt;I have some experience building ActivityPub software outside of AodeRelay. I experimented with a
request-to-federate model in an image gallery platform in 2021&lt;&#x2F;li&gt;
&lt;li&gt;Mentioning Jack Twitter isn&#x27;t super important. From what I&#x27;ve gathered he&#x27;s not very involved in
Bluesky or ATProto anymore.&lt;&#x2F;li&gt;
&lt;li&gt;There exist bridges from ActivityPub to other platforms already (such as Nostr). I have these
bridges blocked from my mastodon server, not for privacy reasons but for moderation reasons.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Ugh Forgejo Actions</title>
        <published>2024-02-10T00:00:00+00:00</published>
        <updated>2024-02-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.asonix.dog/001-forgejo-actions/"/>
        <id>https://blog.asonix.dog/001-forgejo-actions/</id>
        
        <content type="html" xml:base="https://blog.asonix.dog/001-forgejo-actions/">&lt;p&gt;Over the last few days I&#x27;ve figured out how to use Forgejo Actions. I was excited to try it since
it&#x27;s integrated directly into Forgejo these days, and compatibility with github Actions means
there&#x27;s already loads of third party actions to take advantage of. Previously I was using Drone CI.
I still am in a number of projects. But I&#x27;m hoping to get everything moved over to it over the next
week or so.&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s not why I&#x27;m writing this blog post. I&#x27;m writing this blog post because I haven&#x27;t found
very many useful resources for understanding how Actions works, despite the prevalence github
Actions. All the documentation makes it look so simple to use, and in many cases I&#x27;m sure it is, but
when you&#x27;re running it yourself, you&#x27;ll find the edges.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h2&gt;
&lt;p&gt;Setting up Forgejo Actions isn&#x27;t a huge deal. I&#x27;m running it via docker-compose, but it can be run
natively or in kubernetes or with lxc (etc). The one crucial thing though is it needs access to a
docker daemon in order to operate. Giving it a Docker in Docker container is fine. Here&#x27;s my DinD
section:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ocker-in-docker&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker:dind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rivileged&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dockerd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-H&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;tcp:&#x2F;&#x2F;0.0.0.0:2375&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;--tls=false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;6&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lways&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simple enough? Now we&#x27;re going to get a little more complicated with the Runner configuration. The
runner needs to be brought up in 2 steps. The first step registers the runner with Forgejo and
creates the runner configuration file. The second step launches the runner process. This is
unfortunately not as simple as launching the container, but it isn&#x27;t too bad.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; docker-in-docker: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  F&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;orgejo-runner-1-register&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ode.Forgejo.org&#x2F;Forgejo&#x2F;runner:3.3.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker-in-docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      D&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;OCKER_HOST&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cp:&#x2F;&#x2F;docker-in-docker:2375&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;storage&#x2F;Forgejo-actions&#x2F;runner-1:&#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;12&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ser&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;13&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;14&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      bash -ec &amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      if [ -f config.yml ]; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        exit 0 ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;17&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      fi ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;18&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      while : ; do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;19&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        Forgejo-runner register --no-interactive --instance https:&#x2F;&#x2F;git.asonix.dog --name bluestar-runner-1 --token TOKEN &amp;amp;&amp;amp; break ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;20&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        sleep 1 ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;21&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      done ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;22&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      Forgejo-runner generate-config &amp;gt; config.yml ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;23&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      sed -i -e &amp;quot;s|network: .*|network: host|&amp;quot; config.yml ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      sed -i -e &amp;quot;s|labels: \[\]|labels: \[\&amp;quot;docker:docker:&#x2F;&#x2F;bash:alpine3.19\&amp;quot;\]|&amp;quot; config.yml ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;25&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      chown -R 1000:1000 &#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;26&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;      &amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the first step. The script loops attempting to register the runner with Forgejo if there
isn&#x27;t an existing configuration file, and when it succeeds it writes the configuration file and
updates some values.&lt;&#x2F;p&gt;
&lt;p&gt;This can be more-or-less copied verbatim, with the exception of &lt;code&gt;TOKEN&lt;&#x2F;code&gt;, which needs to be copied
from the Forgejo actions admin panel. We&#x27;ll come back to the config.yml file later. Next up we
actually run the runner.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ervices&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; docker-in-docker: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Forgejo-runner-1-register: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  F&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;orgejo-runner-1-daemon&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ode.Forgejo.org&#x2F;Forgejo&#x2F;runner:3.3.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inks&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker-in-docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nvironment&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      D&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;OCKER_HOST&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cp:&#x2F;&#x2F;docker-in-docker:2375&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;11&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;epends_on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;12&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      F&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;orgejo-runner-1-register&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;13&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ondition&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ervice_completed_successfully&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;14&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;olumes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;storage&#x2F;Forgejo-actions&#x2F;runner-1:&#x2F;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Forgejo-runner --config config.yml daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;17&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;estart&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lways&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A lot less going on. We let the Forgejo runner access our Docker-in-Docker daemon and launch it
after the registration container finishes. Off to a great start.&lt;&#x2F;p&gt;
&lt;p&gt;Using my basic &quot;make sure it works&quot; action that I cobbled together after reading some of the
documentation, we can make sure the runner works:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ull_request&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ush&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ranches&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ags&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v*.*.*&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  B&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;INARY&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;xample&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;12&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;13&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;est&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;14&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;trategy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;16&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atrix&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;17&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nfo&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;18&lt;&#x2F;span&gt;&lt;span&gt;          -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rch&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;md64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;          -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rch&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rm64v8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;          -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rch&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rm64v7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;21&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;22&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We can run multiple bash commands, and for each item in our matrix!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cho &amp;quot;${{ matrix.info.arch }} Good&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;25&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;26&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;est2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;27&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;28&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;29&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; we can override the docker image, how fancy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;30&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ebian:bookworm-slim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;31&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cho &amp;quot;Hello, debian&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;33&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;34&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;est3&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;35&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;36&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;37&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker.io&#x2F;asonix&#x2F;rust-builder:latest-linux-arm32v7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;38&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;39&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We can even compile rust code! It&amp;#39;s amazing!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo init --bin --name $BINARY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This all runs successfully when a branch or a tag matching v*.*.* is pushed. We did it! &lt;del&gt;We&#x27;re
done!&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a deliberately simplified version of the setup I actually went through, which involved
&lt;code&gt;bash&lt;&#x2F;code&gt; not existing at first.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s add it to an existing project (say, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;asonix&#x2F;pict-rs&quot;&gt;pict-rs&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ush&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ull_request&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ranches&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;lippy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;11&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker.io&#x2F;asonix&#x2F;rust-builder:latest-linux-arm32v7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;12&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;14&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;heckout pict-rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;17&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lippy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;18&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;19&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          cargo clippy --no-default-features -- -D warnings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;20&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          cargo clippy --no-default-features --features io-uring -- -D warnings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And run it!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OCI runtime exec failed: exec failed: unable to start container process: exec: &amp;quot;node&amp;quot;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;executable file not found in $PATH: unknown&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oh.&lt;&#x2F;p&gt;
&lt;p&gt;...what?&lt;&#x2F;p&gt;
&lt;p&gt;Hmm...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problems&quot;&gt;The Problems&lt;&#x2F;h2&gt;
&lt;p&gt;So actions&#x2F;checkout@v4 depends on node to run, but my rust builder container doesn&#x27;t have node in it
so... I can&#x27;t checkout my code? Well let&#x27;s just split this up a bit, then.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ush&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ull_request&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ranches&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;lone&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;11&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker.io&#x2F;node:20-bookworm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;12&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;14&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;heckout pict-rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;16&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;17&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;lippy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;18&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eeds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lone&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;19&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;20&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;21&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker.io&#x2F;asonix&#x2F;rust-builder:latest-linux-amd64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;22&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;24&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lippy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;25&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;26&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          cargo clippy --no-default-features -- -D warnings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span aria-hidden=&quot;true&quot; class=&quot;giallo-ln&quot;&gt;27&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          cargo clippy --no-default-features --features io-uring -- -D warnings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Except that doesn&#x27;t work. The cloned repo doesn&#x27;t stick around between jobs. If we had more than one
runner the jobs might not even run on the same one! We could try solving this with artifacts but
wait... &lt;code&gt;actions&#x2F;download-artifact@v4&lt;&#x2F;code&gt; also depends on node, so we can&#x27;t run it in the rust-builder
container.&lt;&#x2F;p&gt;
&lt;p&gt;So we have Actions but we can&#x27;t use them. How does github handle this? Well github&#x27;s answer is to
install anything you could ever need into their default actions containers. Meaning node, go,
python, ruby, docker (oh, docker... we&#x27;ll need that too) and more are all bundled into a 60GB image.
If you remember when we had a script that ran &lt;code&gt;sed&lt;&#x2F;code&gt; on the config earlier...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sed&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s|labels: \[\]|labels: \[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;docker:docker:&#x2F;&#x2F;bash:alpine3.19&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\]|&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config.yml&lt;&#x2F;span&gt;&lt;span&gt; ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We were setting a value in the Forgejo runner&#x27;s config to provide our runners with default
containers. We started with &lt;code&gt;bash&lt;&#x2F;code&gt; on &lt;code&gt;alpine&lt;&#x2F;code&gt;. While that particular container is very small and
doesn&#x27;t take long to download, it doesn&#x27;t contain the majority of things that actions expect to
exist.&lt;&#x2F;p&gt;
&lt;p&gt;In order to build pict-rs we need rust, and not just any rust but a rust that is capable of
cross-building (I target armv7, aarch64, and x86_64 with musl libc). In order to clone pict-rs, use
the actions cache, use the actions artifacts, and more we need nodejs. In order to build docker
containers we need docker and qemu. The container image we need to have or make to run our CI is now
nontrivial.&lt;&#x2F;p&gt;
&lt;p&gt;As a proof of concept, I first wrote my actions where I installed everything by hand. I started with
the node:20-bookworm image from dockerhub. I had steps to apt-get install docker, download rustup
and install it, add the proper targets, add clippy, add cargo-binstall,
&lt;code&gt;cargo binstall cargo-zigbuild&lt;&#x2F;code&gt;, and install zig. While this worked, it took a while just in the
setup phase, which isn&#x27;t what we want for CI.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My previous CI for pict-rs used my &lt;code&gt;rust-builder&lt;&#x2F;code&gt; image, which doesn&#x27;t actually use
cargo-zigbuild. I opted to use zig&#x27;s linker for pict-rs in Forgejo Actions because I knew it
would be easier than manually constructing a cross-compile environment. It would also enable me
to use a single container to build for any platform, rather than my previous CI which had a
unique container for each platform I targeted.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So I wrote a bit of caching. I had used an action to install zig, and that action cached zig on the
runner. I wrote my own caching layer for all the rustup and cargo bits. That sped things up as well,
but it still meant using space in the runner cache, and potentially installing everything again on a
cache miss. In this process, I also hit the github rate limit for downloading cargo-zigbuild via
cargo-binstall, meaning I had to start compiling it from crates.io instead (which doesn&#x27;t take too
long, but it&#x27;s still longer than downloading a binary).&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;As an aside, I had to set &lt;code&gt;DOCKER_HOST: tcp:&#x2F;&#x2F;docker-in-docker:2375&lt;&#x2F;code&gt; as an environment variable in
the runner &lt;code&gt;config.yml&lt;&#x2F;code&gt; file so that my use of docker in the actions container would find my
docker-in-docker daemon.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;giving-in&quot;&gt;Giving In&lt;&#x2F;h2&gt;
&lt;p&gt;I decided I needed a universal base container image to run my CI the way github does it, because
it&#x27;s the only way that makes sense for their CI system. If all the actions people write are going to
expect me to have things installed, then I better have them installed. You can find the actions
workflow I use to produce my base image in my
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;asonix&#x2F;actions-base-image&quot;&gt;actions-base-image repository&lt;&#x2F;a&gt;. I&#x27;m sure that in
the future I will encounter more actions that fail to run on this image and I will need to update it
to add more dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;I also wrote another caching action, simpler now than before since all the rust, zig, and docker
bits are baked into the base image. You can find it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.asonix.dog&#x2F;asonix&#x2F;actions&quot;&gt;here&lt;&#x2F;a&gt; in
the &lt;code&gt;cache-rust-dependencies&lt;&#x2F;code&gt; folder. It&#x27;s extremely basic but saves me a download from crates.io
for each job pict-rs runs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so&quot;&gt;So?&lt;&#x2F;h2&gt;
&lt;p&gt;Am I happy with Forgejo Actions? Not really. I think the design of Actions is pretty bad for the
Forgejo Actions case where you control the runners yourself. On github it&#x27;s fine, since github
manages the 60GB image behind the scenes where you never need to think about it. Outside of github
it&#x27;s less ideal. I&#x27;m still going to migrate all my projects to it now that I have everything
working and a not-too-big base image for myself (it&#x27;s 1GB).&lt;&#x2F;p&gt;
&lt;p&gt;I hope anyone else struggling with Actions (github, gitea, forgejo, or otherwise) gains some insight
from this post. It&#x27;s not like I built this blog in the first place to be able to put this online or
anything. Let&#x27;s hope now that I&#x27;ve written all this that I don&#x27;t need to update my base image to
publish this to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;garagehq.deuxfleurs.fr&#x2F;&quot;&gt;garage&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I ended up adding &lt;code&gt;minio-client&lt;&#x2F;code&gt; to my base image in order to publish this&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
</feed>
