<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Package Forge]]></title><description><![CDATA[Blog, News, Reports from across the entire PkgForge ORG/Sub-ORG]]></description><link>https://blog.pkgforge.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 18:21:14 GMT</lastBuildDate><atom:link href="https://blog.pkgforge.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Cross-Compiling 10,000+ Go CLI Packages Statically]]></title><description><![CDATA[🤖
AI translation tools were used to assist with language clarity, as our research team are not native English speakers. We believe the quality of our research and findings will speak for themselves


TL;DR
Built 17k Go CLI tools as static binaries u...]]></description><link>https://blog.pkgforge.dev/cross-compiling-10000-go-cli-packages-statically</link><guid isPermaLink="true">https://blog.pkgforge.dev/cross-compiling-10000-go-cli-packages-statically</guid><category><![CDATA[Go Language]]></category><category><![CDATA[golang]]></category><category><![CDATA[package manager]]></category><category><![CDATA[scale]]></category><category><![CDATA[cli]]></category><dc:creator><![CDATA[Ajam]]></dc:creator><pubDate>Tue, 01 Jul 2025 08:10:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751209703264/12cfe04f-61d9-4857-9e8b-fefdf290435f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">🤖</div>
<div data-node-type="callout-text">AI translation tools were used to assist with language clarity, as our research team are not native English speakers. We believe the quality of our research and findings will speak for themselves</div>
</div>

<h2 id="heading-tldr">TL;DR</h2>
<p>Built 17k Go CLI tools as static binaries using Zig cross-compilation. Install with <a target="_blank" href="http://github.com/pkgforge/soar"><code>soar install package-name</code></a> instead of <code>go install</code>. No Go toolchain required. 67% success rate, 1:10:10 ratio of modules to executables.</p>
<p><strong>No more dumpster diving through GitHub repos to find quality CLI tools.</strong> Pre-built static binaries that work everywhere, instantly.</p>
<h2 id="heading-faq">FAQ</h2>
<p><strong>Q: Why not just use</strong> <code>go install</code>?<br />A: If you're a Go developer, <code>go install</code> works great for you. This is for end users who want CLI tools without installing Go - sysadmins, DevOps folks, or anyone who just wants tools to work.</p>
<p><strong>Q: What about package managers like apt/homebrew?</strong><br />A: Static binaries work everywhere without dependency hell. One binary runs on any Linux distro, any version, without requiring specific library versions.</p>
<p><strong>Q: Is this secure? You're redistributing random code.</strong><br />A: All builds run in isolated GitHub Actions with public logs. Every binary has build provenance, attestations, and checksums. You can verify exactly what was built and how.</p>
<p><strong>Q: Why Zig specifically?</strong><br />A: Go's built-in cross-compilation is excellent for standard static binaries, but we specifically need static PIE (Position Independent Executable) binaries. When using <code>-buildmode=pie</code> on glibc systems like GitHub Actions, Go produces dynamically linked executables and generates static linking warnings. Zig elegantly solves this by providing musl libc, which natively supports static PIE binaries without the glibc complications - giving us the security benefits of PIE while maintaining true static linking. See: <a target="_blank" href="https://github.com/golang/go/issues/64875">https://github.com/golang/go/issues/64875</a>, <a target="_blank" href="https://gitlab.alpinelinux.org/alpine/aports/-/issues/15809">https://gitlab.alpinelinux.org/alpine/aports/-/issues/15809</a>, <a target="_blank" href="https://bugs.gentoo.org/924632">https://bugs.gentoo.org/924632</a></p>
<p><strong>Q: What happens when builds fail?</strong><br />A: Build logs are public, and we're considering auto-filing issues upstream to help maintainers fix cross-compilation problems.</p>
<hr />
<h1 id="heading-intro">Intro</h1>
<p><a target="_blank" href="https://docs.pkgforge.dev/"><strong>Pkgforge</strong></a> hosts the <a target="_blank" href="https://docs.pkgforge.dev/soar/readme/packages#total">world's largest collection</a> of <a target="_blank" href="https://github.com/orgs/pkgforge/packages">prebuilt</a>, <a target="_blank" href="https://docs.pkgforge.dev/repositories/bincache">static binaries</a> that work everywhere without dependencies. While our <a target="_blank" href="https://docs.pkgforge.dev/repositories">main repos</a> include hand-picked packages and manually maintained by our team, we had an ambitious idea: what if we could automatically harvest CLI tools from ecosystems like Go's module registry, build them as static binaries using Zig's powerful cross-compilation capabilities, and made them <a target="_blank" href="https://github.com/pkgforge/soar">available to everyone</a>?</p>
<p>Instead of manually curating every package, we decided to tap into existing package ecosystems and automate the entire process. After two weeks of intensive development and countless iterations, we made this idea a reality.</p>
<p>We also recommend reading our previous post: <a target="_blank" href="https://blog.pkgforge.dev/cross-compiling-10000-rust-cli-crates-statically">Cross-Compiling 10,000+ Rust CLI Crates Statically</a>, as that contains some background/context which will be relevant later in this post.</p>
<hr />
<h1 id="heading-ingesting-go-modules">Ingesting Go Modules</h1>
<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">We will use the term go module &amp; go package interchangeably, for the sake of simplicity.</div>
</div>

<p>When we started this project, we assumed Go would have something resembling Rust's <a target="_blank" href="http://crates.io">crates.io</a>—a proper package registry with APIs, metadata, and basic ecosystem tooling. We discovered the reality was quite different.</p>
<p>Our journey began with what seemed like the obvious approach: scraping <a target="_blank" href="http://pkg.go.dev">pkg.go.dev</a>. After all, this is Google's official Go package discovery site, beautifully displaying exactly the metadata we needed—descriptions, repository information, and package statistics. The site had everything we wanted in a gorgeous, human-readable format, so surely they'd provide an API for programmatic access?</p>
<p>Unfortunately, this approach proved unreliable. We spent considerable time building scrapers, only to encounter frequent failures as the site's responses changed or received 403 errors when our requests appeared automated.</p>
<p>What made this particularly maddening was seeing all the data we needed displayed right there on the website, but completely inaccessible through any official API. There's been <a target="_blank" href="https://github.com/golang/go/issues/36785">a GitHub issue requesting this basic functionality since 2020</a>, and it remains stubbornly ignored by the Go team.</p>
<p>It was only after this frustrating waste of time that we discovered the truth buried in <a target="_blank" href="http://pkg.go.dev">pkg.go.dev</a>'s <a target="_blank" href="https://pkg.go.dev/about#adding-a-package">about page</a>: they source their data from the <a target="_blank" href="https://index.golang.org/">Go Module Index</a>. This, however highlights a fundamental difference in design philosophy: while Rust makes their registry API prominent and easily accessible, Go's decentralized approach means finding this info takes some digging.</p>
<h2 id="heading-trials-amp-tribulations">Trials &amp; Tribulations</h2>
<p>Once we found the Module Index, we were forced to develop a multi-pronged strategy combining several data sources:</p>
<ul>
<li><p><a target="_blank" href="https://proxy.golang.org/"><strong>The Go Module Index</strong></a> (the buried treasure we should have found on day one)</p>
</li>
<li><p><strong>GitHub's API</strong> for repositories with Go CLI tags and topics (because the Module Index provides zero metadata about package purpose)</p>
</li>
<li><p><a target="_blank" href="http://github.com/avelino/awesome-go"><strong>Community-curated lists</strong></a> of Go CLI utilities (maintained by volunteers because Google won't)</p>
</li>
<li><p><strong>Scraping</strong> <a target="_blank" href="http://deps.dev"><strong>deps.dev</strong></a> (Google's <em>other</em> package service that actually works)</p>
</li>
<li><p><strong>Web scraping</strong> <a target="_blank" href="http://pkg.go.dev"><strong>pkg.go.dev</strong></a> when all else failed (since they still won't provide an API)</p>
</li>
</ul>
<p>For comparision, contrast this with what we had to do in our previous blog: <a target="_blank" href="https://blog.pkgforge.dev/cross-compiling-10000-rust-cli-crates-statically#heading-ingesting-cratesio">https://blog.pkgforge.dev/cross-compiling-10000-rust-cli-crates-statically#heading-ingesting-cratesio</a>: we can simply download their <a target="_blank" href="https://static.crates.io/db-dump.tar.gz">complete database dump</a>, query it locally, and have instant access to comprehensive metadata for every package. No scraping, no downloading source code, no heuristic analysis—just clean, structured data that respects developers' time and computational resources.</p>
<p>This revealed some challenges with Go's minimalist design philosophy when it comes to ecosystem tooling. Unlike Rust's ecosystem where <code>Cargo.toml</code> explicitly declares binaries, categories, keywords, and descriptions, Go's "simplicity-first" approach created a nightmare of discovery.</p>
<p>Rust doesn't just excel at manifest design—they actually care about their ecosystem. They provide <a target="_blank" href="https://static.crates.io/db-dump.tar.gz">complete database dumps</a> and have thoughtful policies like <a target="_blank" href="https://rust-lang.github.io/rfcs/3463-crates-io-policy-update.html#data-access">RFC 3463</a> that genuinely support developers and researchers. Meanwhile, Go provides:</p>
<ul>
<li><p>No central registry like <a target="_blank" href="http://crates.io">crates.io</a></p>
</li>
<li><p>No standardized metadata format</p>
</li>
<li><p>No proper package manager (just <code>go get</code> which is barely more than a glorified downloader)</p>
</li>
<li><p>No way to programmatically determine what a package actually <em>does</em> without downloading and analyzing its source code</p>
</li>
</ul>
<p>Go's module system makes it stupidly hard to answer basic questions like 'what does this package do?’. While Rust has <code>cargo search</code>, <code>cargo info</code>, and rich metadata queries, Go developers are stuck with a system that can't even tell you what a package does without downloading it first. There's no package statistics, no trending packages, no search functionality beyond basic text matching—essentially none of the features that make a package ecosystem usable at scale.</p>
<p>These architectural decisions led us to build a sophisticated toolchain of four separate utilities to answer questions like "Is this package a CLI tool?"</p>
<ul>
<li><p><a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools/go-indexer"><strong>go-indexer</strong></a>: Fetches modules list from the Module Index</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751345803380/e5dea59c-0bd4-420a-ad99-df7220a9f51d.gif" alt class="image--center mx-auto" /></p>
</li>
<li><p><a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools/go-enricher"><strong>go-enricher</strong></a>: The digital scavenger that enriches our sparse dataset by scraping <a target="_blank" href="http://deps.dev">deps.dev</a> (ironically, also built by Google), GitHub's API, and whatever other third-party services we can find— An absurd workaround that highlights the dysfunction of Go's registry. While <a target="_blank" href="http://deps.dev">deps.dev</a> shows Google clearly understands the problem and how to solve it, they continue to maintain a "minimalist" module system that offers virtually none of this functionality natively, refusing to integrate such capabilities into official tooling.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751345841146/2749fd31-ea8a-4a7f-8b6e-6d6033278df7.gif" alt class="image--center mx-auto" /></p>
</li>
<li><p><a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools/filter-urls"><strong>filter-urls</strong></a>: Removes unreachable download URLs to prevent build failures—because of course the "decentralized" system has reliability issues.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751345863629/a9772943-5d7a-4591-89b7-47f87d25767c.gif" alt class="image--center mx-auto" /></p>
</li>
<li><p><a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools/go-detector"><strong>go-detector</strong></a>: The crown jewel of Go's registry dysfunction: a system that downloads, extracts, and analyzes tens of thousands of Go modules with complex code analysis and scoring algorithms—just to determine if a package is a CLI tool. We're burning gigabytes of bandwidth and compute parsing ASTs and import patterns to answer a question that should be a single field in a manifest.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751345885879/737266c8-4343-44c7-974f-524f7b0a3775.gif" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p>So while the Go team clearly understands the value of package metadata (they built an entire website around it), they've deliberately chosen not to make it programmatically accessible, forcing every tooling developer to become a digital archaeologist. A well-designed ecosystem <em>would</em> provide comprehensive search, rich metadata, usage stats, trending insights, integrated tooling, full workflows for initialization, publishing, testing, and documentation, along with open data access for researchers and developers. Instead, Go gives us <code>go get</code>—basically <code>git clone</code> with extra steps—and calls it a day.</p>
<p>After building an <a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools">entire toolchain</a> out of necessity and automating it with <a target="_blank" href="https://github.com/pkgforge-go/builder/actions/workflows/gen_data.yaml">GitHub Actions</a>, we now <a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/data">generate everything ourselves</a>—but it shouldn't have taken four tools and industrial-scale source analysis to answer basic questions about Go packages. All of this could have been avoided if Go simply offered what other ecosystems have for years: proper registries with real APIs, metadata, and tooling support. Go's 'keep it simple' philosophy created a Rube Goldberg machine for package discovery, while other ecosystems prove that developer-friendly design is both possible and actively maintained.</p>
<hr />
<h1 id="heading-package-selection">Package Selection</h1>
<pre><code class="lang-bash">$ go-indexer --start-date <span class="hljs-string">"2024-01-01"</span> --output <span class="hljs-string">"./INDEX.jsonl"</span> --verbose
Go Modules Index Fetcher
┌────────────────────────────────────────────────────────────┐
│ Configuration                                              │
├────────────────────────────────────────────────────────────┤
│ Start date                   :                  2024-01-01 │
│ End date                     :                  2025-07-01 │
│ Output file                  :               ./INDEX.jsonl │
│ Max concurrent               :                          30 │
│ Max retries                  :                           3 │
│ Batch size                   :                        2000 │
│ Timeout                      :                         30s │
│ Dry run                      :                       <span class="hljs-literal">false</span> │
│ Resume mode                  :                       <span class="hljs-literal">false</span> │
│ Process output               :                        <span class="hljs-literal">true</span> │
└────────────────────────────────────────────────────────────┘
📅 Generated 547 dates to process
📂 Temp directory: /tmp/.tmpWhWALv
📦 Combining daily files into final output...
📋 Combining [████████████████████████████████████████] 547/547 files ✓ 18518000 total lines                                                                                                 🔄 Post-processing output file...
🔍 Processing ✓ Processed 18518000 lines                                                                                                                                                     📊 Grouping 1515437 unique sources...
💾 Writing processed output...
✅ Post-processing complete!
📄 Processed file: ./INDEX.processed.json
📊 Unique sources: 1515437
🏷️  Total versions: 17982265

🎉 Processing Complete!
┌────────────────────────────────────────────────────────────┐
│ Final Statistics                                           │
├────────────────────────────────────────────────────────────┤
│ Duration                     :                     233.10s │
│ Days processed               :                     547/547 │
│ Total records                :                    18518000 │
│ Errors                       :                           0 │
│ Rate                         :           79444 records/sec │
└────────────────────────────────────────────────────────────┘
📊 Final output: ./INDEX.jsonl (2352.59 MB, 18518000 lines)
</code></pre>
<p>Since we ended up with ~ 1.5 Million Go modules, we needed to set some constraints &amp; filter for what we actually wanted to build:</p>
<ol>
<li><p>Must be indexed by <a target="_blank" href="http://index.golang.org">index.golang.org</a> within the last year i.e &gt; <code>2024-01-01</code></p>
</li>
<li><p>Must have proper description, home page etc. from our <a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools/go-enricher">go-enricher</a></p>
</li>
<li><p>Must be a CLI &amp; pass our <a target="_blank" href="https://github.com/pkgforge-go/builder/tree/main/tools/go-detector">go-detector</a>.</p>
</li>
<li><p>Must have a reasonable number of GitHub stars (&gt; 2) or downloads to indicate community usage</p>
</li>
</ol>
<pre><code class="lang-bash">🐹 Total Unique Modules (2024+):   ████████████████████████████████████████████████████████████ 1,515,437
    ↓
☑️ Selected/Eligible Modules:      ████████████████████████████████████████▌                    516,694
    ↓
🧬 Enriched with deps.dev API:     ███████████████████████████████████▌                         331,333
    ↓
🔗 Filtered <span class="hljs-keyword">for</span> cached URLs:       ████████████████████████████▌                                250,391
    ↓
🔩 Filtered <span class="hljs-keyword">for</span> CLI packages:      ███████████▌                                                 72,496
    ↓
🔧 Filtered <span class="hljs-keyword">for</span> Popularity:        █████▌                                                       17,039

✅ Modules to Build: 17,039
// Total unique modules whose metadata was scraped/fetched: 1,515,437 (&gt; date -d <span class="hljs-string">'last year'</span> <span class="hljs-string">'+%Y-01-01'</span>)  
// Total modules that matched the selection criteria: 516,694
// Total modules enriched with deps.dev API: 331,333
// Total modules that are actually cached: 250,391
// Total modules detected as CLI: 72,496
// Total modules to build: 17,039
</code></pre>
<p>We ended up with ~ 17,000 Go modules that we now planned to compile.</p>
<hr />
<h1 id="heading-build-tool">Build Tool</h1>
<p>With over 17,000 modules to build on individual GitHub Actions runners, speed was paramount. While Go offers excellent built-in cross-compilation, we needed to use musl for pure static linking &amp; also to avoid things like:</p>
<pre><code class="lang-bash">warning: Using <span class="hljs-string">'getpwnam_r'</span> <span class="hljs-keyword">in</span> statically linked applications requires at runtime the shared libraries from the glibc version used <span class="hljs-keyword">for</span> linking
warning: Using <span class="hljs-string">'getaddrinfo'</span> <span class="hljs-keyword">in</span> statically linked applications requires at runtime the shared libraries from the glibc version used <span class="hljs-keyword">for</span> linking
</code></pre>
<p>Packages trying to link with external system libraries via <code>CGO</code> (other than ibc) will fail by design, as we target pure Go implementations.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">CGO is enabled only for Zig's linker - we're not linking arbitrary system libraries. Packages requiring external C libraries beyond libc will fail by design.</div>
</div>

<p>Our <a target="_blank" href="https://github.com/pkgforge/devscripts/pkgs/container/devscripts%2Falpine-builder">heavy docker images</a> used for <a target="_blank" href="https://github.com/search?q=repo%3Apkgforge%2Fsoarpkgs%20docker%20run&amp;type=code">official packages</a> consumed 2-3 minutes just for pulling and extraction, making them unsuitable for this scale. We needed a solution that was minimal &amp; worked out of the box.</p>
<p>Enter <a target="_blank" href="https://ziglang.org/">Zig</a>: The C/C++ cross-compiler toolchain, which provides:</p>
<ul>
<li><p><strong>Zero setup cross-compilation</strong>: No need for target-specific toolchains</p>
</li>
<li><p><strong>Universal C/C++ compiler</strong>: Single installation handles all our target architectures</p>
</li>
<li><p><strong>Fast compilation</strong>: Minimal overhead compared to traditional cross-compilation setups or containers</p>
</li>
<li><p><strong>MUSL for Static linking</strong> : Perfect for our portable binary goals</p>
</li>
</ul>
<p>We also used <a target="_blank" href="https://github.com/jpeddicord/askalono">jpeddicord/askalono</a> to automatically detect &amp; copy over licenses.</p>
<hr />
<h1 id="heading-build-constraints">Build Constraints</h1>
<p>To achieve truly portable, optimized, and statically linked relocatable binaries, we applied the following comprehensive build constraints using CGO with Zig as our cross-compiler:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#Build Environment</span>
<span class="hljs-built_in">export</span> CGO_ENABLED=1
<span class="hljs-built_in">export</span> CGO_CFLAGS=<span class="hljs-string">"-O2 -flto=auto -fPIE -fpie -static -w -pipe"</span>
<span class="hljs-built_in">export</span> CC=<span class="hljs-string">"zig cc -target <span class="hljs-variable">${target_triplet}</span>"</span>
<span class="hljs-built_in">export</span> CXX=<span class="hljs-string">"zig c++ -target <span class="hljs-variable">${target_triplet}</span>"</span>
<span class="hljs-built_in">export</span> GOOS=linux
<span class="hljs-built_in">export</span> GOARCH=<span class="hljs-variable">${TARGET_ARCH}</span>

<span class="hljs-comment">#Go Build Flags</span>
go build -a -v -x -trimpath \
         -buildmode=<span class="hljs-string">"pie"</span> \
         -buildvcs=<span class="hljs-string">"false"</span> \
         -ldflags=<span class="hljs-string">"-s -w -buildid= -linkmode=external"</span> \
         -tags <span class="hljs-string">'netgo,osusergo'</span> \
         -extldflags=<span class="hljs-string">"-s -w -static-pie -Wl,--build-id=none"</span>
</code></pre>
<ol>
<li><p><a target="_blank" href="https://wiki.archlinux.org/title/Go_package_guidelines"><strong>Static PIE (Position Independent Executable)</strong></a>: <code>-buildmode=pie</code> with <code>-static-pie</code> creates relocatable static binaries</p>
</li>
<li><p><a target="_blank" href="https://pkg.go.dev/cmd/cgo"><strong>CGO Enabled</strong></a>: <code>CGO_ENABLED=1</code> allows interaction with C libraries (Core only) while maintaining static linking</p>
</li>
<li><p><a target="_blank" href="https://wiki.gentoo.org/wiki/GCC_optimization"><strong>Optimized CGO</strong></a>: <code>CGO_CFLAGS=-O2 -flto=auto -fPIE -fpie -static -w -pipe</code> enables LTO and position independence</p>
</li>
<li><p><a target="_blank" href="https://go.dev/src/net/conf.go"><strong>Pure Go Networking</strong></a>: <code>-tags 'netgo'</code> uses Go's native network stack instead of libc</p>
</li>
<li><p><a target="_blank" href="https://pkg.go.dev/os/user"><strong>Pure Go User/Group</strong></a>: <code>-tags 'osusergo'</code> avoids libc for user/group lookups</p>
</li>
<li><p><a target="_blank" href="https://zig.guide/build-system/cross-compilation/"><strong>Zig Cross-Compilation</strong></a>: Uses Zig as the C/C++ compiler for seamless cross-compilation with static linking</p>
</li>
<li><p><strong>Fully Stripped</strong>: <code>-trimpath -buildvcs=false -buildid=</code> remove all debug info, symbols, and build IDs</p>
</li>
<li><p><strong>No System Libraries</strong>: <code>CGO</code> is used only for the zig linker, not arbitrary system C library.</p>
</li>
</ol>
<blockquote>
<pre><code class="lang-bash"><span class="hljs-comment">#These modules would error out in the following manner</span>
error: could not find system library required by CGO
error <span class="hljs-keyword">while</span> loading shared libraries: nameofthelib.so.1: cannot open shared object file: No such file or directory
</code></pre>
</blockquote>
<hr />
<h1 id="heading-build-targets">Build Targets</h1>
<p>While <a target="_blank" href="https://github.com/pkgforge/soar"><strong>Soar</strong></a> supports any <strong><em>Unix-based Distro</em></strong>, due to <a target="_blank" href="https://github.com/actions/runner/issues/385">lack of CI support for other Unix Kernel on GitHub Runners</a> (natively, not VMs), we are limited to <strong>Linux</strong> only. We further refined our target matrix by excluding architectures approaching end-of-life:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>HOST_TRIPLET</strong></td><td><strong>GOOS/GOARCH</strong></td><td><strong>ZIG_TARGET</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>aarch64-Linux</code></td><td><code>linux/arm64</code></td><td><code>aarch64-linux-musl</code></td></tr>
<tr>
<td><code>loongarch64-Linux</code></td><td><code>linux/loong64</code></td><td><code>loongarch64-linux-musl</code></td></tr>
<tr>
<td><code>riscv64-Linux</code></td><td><code>linux/riscv64</code></td><td><code>riscv64-linux-musl</code></td></tr>
<tr>
<td><code>x86_64-Linux</code></td><td><code>linux/amd64</code></td><td><code>x86_64-linux-musl</code></td></tr>
</tbody>
</table>
</div><hr />
<h1 id="heading-build-security">Build Security</h1>
<p>We are aware of supply chain security concerns in package ecosystems, so we wanted this to be <a target="_blank" href="https://docs.pkgforge.dev/repositories/soarpkgs/security">as secure as our official repositories</a>, by ensuring:</p>
<ul>
<li><p>Modules are downloaded from official <a target="_blank" href="https://proxy.golang.org/">Go proxy servers</a>, like the official Go toolchain does</p>
</li>
<li><p>CI/CD run on <a target="_blank" href="https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions">GitHub Actions</a>, with temporary, scoped tokens per package</p>
</li>
<li><p>Build Logs are viewable using: <code>soar log ${PKG_NAME}</code></p>
</li>
<li><p>Build Src is downloadable by downloading: <a target="_blank" href="https://github.com/orgs/pkgforge-go/packages?tab=packages&amp;q=srcbuild"><code>{GHCR_PKG}-srcbuild-${BUILD_ID}</code></a></p>
</li>
<li><p><a target="_blank" href="https://github.com/pkgforge-go/builder/attestations">Artifact Attestation</a> &amp; <a target="_blank" href="https://github.com/pkgforge-go/builder/attestations">Build Provenance</a> are created/updated per build</p>
</li>
<li><p>Checksums are generated (&amp; verified at install time by Soar) for each &amp; every artifact per build</p>
</li>
</ul>
<p>These measures ensure that even if a malicious module attempts to compromise the system, its impact is isolated and cannot affect other modules' integrity.</p>
<hr />
<h1 id="heading-build-workflow">Build Workflow</h1>
<p>17,000 multiplied by 4 targets, meant we would need to run ~ 70,000 instances of CI &amp; also handle <a target="_blank" href="https://github.com/pkgforge-go/builder/tree/metadata">metadata</a>, <a target="_blank" href="https://github.com/pkgforge-go/builder/blob/main/.github/workflows/matrix_builds.yaml">sanity checks</a>, <a target="_blank" href="https://github.com/orgs/pkgforge-go/packages?repo_name=builder">uploading to ghcr</a>, all at the same time. We also set up a discord webhook to stream real-time progress updates to our <a target="_blank" href="https://discord.gg/djJUs48Zbu">discord server</a>.</p>
<pre><code class="lang-mermaid">graph TD
  A[🐹 Go Module Registry] --&gt;|📊 Scrape Metadata 🧬| B[🔍 Filter &amp; Queue ⏳]
  B --&gt; C[🏗️ GitHub Actions Matrix 🔄]
  C --&gt; D[⚡ Zig Cross Compiler ⚒️]
  D --&gt; E[📦 Static Binaries 🛠️]
  E --&gt; F[🗄️ GHCR Registry ⬆️]
  F --&gt;|📊 Generate Metadata 🧬| B
  F --&gt; G[🚀 Soar ⬇️]
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751351112255/ce2cd881-0826-4a86-a98b-d5165bc4c9fe.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751351309106/5b9e9ef4-b2ce-42b1-b7d3-7fb0ca31a0bb.png" alt class="image--center mx-auto" /></p>
<hr />
<h1 id="heading-key-insights-and-findings">Key Insights and Findings</h1>
<h2 id="heading-build-success-vs-failure">Build Success vs. Failure</h2>
<p>At the time of writing (2025-07-01), we have queued ~ 12000 out of the total ~ 17000 modules. We approached this project with optimistic expectations but encountered a sobering reality.</p>
<pre><code class="lang-bash">🏗️ Build Pipeline by Success Rate
─────────────────────────────────────────────────────────────────────────
✅ Queued    ████████████████████████████████████████████████████████████ 11,866 (100.0%)
⚙️ Built     ██████████████████████████████████▌                          8,007 (67.5%)
❌ Failed    ████████████████████▌                                        3,859 (32.5%)
─────────────────────────────────────────────────────────────────────────
</code></pre>
<p>So what went wrong? We sampled about 100 of these error logs &amp; concluded:</p>
<ol>
<li><p><strong>CGO Dependencies with System Libraries</strong>: The majority of failures stemmed from modules requiring CGO with system libraries that couldn't be statically linked or weren't available in our build environment</p>
</li>
<li><p><strong>PIE Build Mode Compatibility</strong>: Some modules or their dependencies don't support Position Independent Executable (PIE) build mode</p>
</li>
<li><p><strong>Platform-Specific Code</strong>: Many modules include platform-specific code or build constraints that fail during cross-compilation to newer architectures</p>
</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-comment">#These typically fail cross-compilation</span>
Modules that:
- Require dynamic system libraries that can<span class="hljs-string">'t be statically linked
- Don'</span>t support PIE (Position Independent Executable) build mode
- Include assembly code <span class="hljs-keyword">for</span> specific architectures
- Use CGO with complex system library dependencies
- Rely on runtime feature detection that conflicts with static PIE

<span class="hljs-comment">##Examples</span>

<span class="hljs-comment"># CGO dependency failures</span>
error: could not find system library <span class="hljs-string">'libgtk-3'</span> required by CGO
ld: library not found <span class="hljs-keyword">for</span> -lssl

<span class="hljs-comment"># PIE compatibility issues  </span>
relocation R_X86_64_32 against symbol `main.version<span class="hljs-string">' can not be used when making a PIE object
linkmode external not supported on linux/riscv64

# Architecture-specific failures
undefined: syscall.SYS_EPOLL_CREATE1
build constraints exclude all Go files in package</span>
</code></pre>
<p>Despite Go's excellent cross-compilation story, <strong>CGO dependencies with system libraries and PIE build mode compatibility remain the primary obstacles to universal static PIE compilation</strong>. This reinforces our strategy of targeting CLI tools that can be fully statically linked with minimal external dependencies.</p>
<hr />
<h2 id="heading-modules-vs-executables">Modules vs Executables</h2>
<p>Another interesting insight from building at scale: many Go modules produce multiple executables. The ~ 8,000 modules we built successfully generated ~ 80,000 individual executables (Also referred to as binaries or packages)</p>
<pre><code class="lang-bash">🏗️ Build Pipeline by Executables
───────────────────────────────────────────────────────────────────────────────
📦 Modules Built       ████                                                       8,007 (100.0%) <span class="hljs-comment">#Base Line</span>
⚙️ Total Executables   ████████████████████████████████████████████████████████   80,082 (10x)
────────────────────────────────────────────────────────────────────────────────
</code></pre>
<p>This 1:10:10 ratio reveals how rich the Go CLI ecosystem actually is, with many projects providing comprehensive toolsuites rather than single utilities.</p>
<hr />
<h2 id="heading-native-vs-cross">Native vs Cross</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">This counts the executables generated &amp; not individual modules. A single module may generate multiple executables. (See Above)</div>
</div>

<pre><code class="lang-bash">🏗️ Build Pipeline by Architecture
─────────────────────────────────────────────────────────────────────────────────
🖥️  x86_64-Linux      ████████████████████████████████████████████████████████ 20,423 (100.00%) <span class="hljs-comment">#Base Line</span>
🖥️  aarch64-Linux     ███████████████████████████████████████████████████████  20,025 (98.05%)
🖥️  riscv64-Linux     ███████████████████████████████████████████████████████  20,167 (98.75%)
🖥️  loongarch64-Linux ██████████████████████████████████████████████████████   19,467 (95.32%)
─────────────────────────────────────────────────────────────────────────────────
</code></pre>
<p>The consistent success rates across architectures demonstrate Go's excellent cross-platform story, with Zig providing seamless CGO cross-compilation. Newer architectures like loongarch64 show slightly lower compatibility rates, suggesting that architecture-specific code assumptions remain common in the ecosystem.</p>
<p><strong>An interesting anomaly</strong>: riscv64-Linux has more executables than aarch64-Linux. This discrepancy occurs because some modules successfully build for non-standard targets like <code>loongarch64-Linux</code> and <code>riscv64-Linux</code> but fail for standard architectures due to build hooks and conditional compilation that trigger differently across targets.</p>
<p>You can explore detailed per-target build results here: <a target="_blank" href="https://github.com/pkgforge-go/builder/blob/main/data/PKGS_BUILT.json">PKGS_BUILT.json</a></p>
<hr />
<h2 id="heading-ci-performance-metrics">CI Performance Metrics</h2>
<p>Our primary build workflow (<a target="_blank" href="https://github.com/pkgforge-go/builder/actions/workflows/matrix_builds.yaml">matrix_builds.yaml</a>) handles the bulk of compilation, with additional workflows managing metadata and miscellaneous tasks. As we implement incremental builds (only rebuilding updated modules) and caching strategies, these metrics will improve significantly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751355917045/30bdf46e-1046-4bbd-bc40-2b66c36101ea.png" alt class="image--center mx-auto" /></p>
<p>Average build time was ~ 2.5 minutes (slower than Rust because we try to build all packages with <code>main</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751355992560/cdd77f74-0a85-445b-8200-f7d57367005c.png" alt class="image--center mx-auto" /></p>
<hr />
<h1 id="heading-review">Review</h1>
<h2 id="heading-compilation-vs-prebuilt-distribution">Compilation vs. Prebuilt Distribution</h2>
<p>Compilation will always be slower than fetching prebuilt binaries, but the degree varies significantly based on module complexity and dependency count. For our demonstration, we'll use <a target="_blank" href="https://github.com/jesseduffield/lazygit">lazygit</a> as a representative example, - results will vary significantly with more complex, dependency-heavy modules.</p>
<p><em>Note: We're not measuring CPU, disk, memory, or bandwidth usage here—try it yourself to experience the full performance difference.</em></p>
<h3 id="heading-go-install">Go Install</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751356624858/aba8774f-3f44-4441-90b1-dcfe9978cb26.gif" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">$ time go install -v <span class="hljs-string">"github.com/jesseduffield/lazygit@latest"</span>
real    0m20.392
user    1m9.520s
sys     0m14.904s
</code></pre>
<h3 id="heading-soar">Soar</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751357063210/8840ed8c-762b-47e4-af2f-8c7fbf74f5b3.gif" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash"><span class="hljs-comment">#Soar uses pkg_ids to ensure exact match because we have too many packages</span>
$ time soar install <span class="hljs-string">"lazygit#github.com_jesseduffield_lazygit:pkgforge-go"</span>
real    0m4.371s
user    0m0.181s
sys     0m0.152s
</code></pre>
<p><strong>Go's native tooling</strong> provides:</p>
<ul>
<li><p>Seamless integration with the Go ecosystem</p>
</li>
<li><p>Automatic dependency resolution</p>
</li>
<li><p>Built-in cross-compilation support</p>
</li>
<li><p>Direct access to latest versions</p>
</li>
</ul>
<p><a target="_blank" href="https://github.com/pkgforge/soar"><strong>Soar</strong></a> is different. We're not trying to replace <code>go install</code> for developers—we're making CLI tools accessible to everyone who just wants stuff to work without installing Go.</p>
<hr />
<h1 id="heading-conclusion">Conclusion</h1>
<p>What started as let's build everything turned into a deep dive on Go's ecosystem quirks and why Zig is genuinely magical for cross-compilation.</p>
<h2 id="heading-key-discoveries-and-implications">Key Discoveries and Implications</h2>
<p><strong>The Go CLI ecosystem is remarkably mature and productive.</strong> Our 1:10:10 ratio of executables to modules reveals that the community is building comprehensive toolsuites with multiple utilities per project. This multiplier effect means that successfully building even a subset of available modules provides exponentially more value to end users.</p>
<p><strong>Zig as a cross-compilation toolchain with CGO is transformative.</strong> By using Zig as our C/C++ compiler with CGO enabled, we eliminated the traditional complexity of cross-compilation toolchain setup while maintaining the ability to statically link libC dependencies and create PIE binaries. Zig’s toolchain is magic.</p>
<p><strong>Static PIE linking remains both powerful and challenging.</strong> The ability to produce truly portable, relocatable binaries that work across any Linux distribution without dependencies is transformative for CLI tool distribution. However, achieving this with PIE (Position Independent Executable) mode requires careful consideration of dependencies and build strategies, even with Go's excellent standard library.</p>
<h2 id="heading-broader-ecosystem-implications">Broader Ecosystem Implications</h2>
<p>Our work demonstrates that automated, large-scale binary distribution can significantly improve developer and end-user experience. The time savings—from over 20 seconds of compilation time to under 5 seconds of download time—represent meaningful productivity improvements.</p>
<p>More importantly, this approach democratizes access to Go CLI tools. Users no longer need Go installed, don't need to understand module paths, and can avoid compilation wait times. They can simply install and use tools, lowering the barrier to entry for adopting Go-based CLI utilities.</p>
<hr />
<h1 id="heading-future-roadmap">Future Roadmap</h1>
<p>The <a target="_blank" href="https://github.com/pkgforge-go/builder/">pkgforge-go</a> project will likely see these additions/improvements in the near future:</p>
<ul>
<li><p><strong>Automated updates</strong>: Rebuild modules when new versions are published (this is partially implemented)</p>
</li>
<li><p><strong>Integration with Go toolchain</strong>: Maybe something similar to <code>go install</code> (specify a module path directly) but with prebuilt binaries</p>
</li>
<li><p><strong>Build optimization</strong>: Optimize CI Build times &amp; reduce failures through better CGO handling</p>
</li>
<li><p><strong>Contribute Upstream</strong>: Opt-in system to automatically create GitHub issues with build logs when module compilation fails, helping maintainers improve cross-compilation compatibility</p>
</li>
<li><p><strong>Community Feedback</strong>: Listen to our users &amp; the community to improve this project &amp; hope for a <a target="_blank" href="https://docs.pkgforge.dev/repositories/soarpkgs/re-distribution">widespread adoption beyond Soar</a></p>
</li>
</ul>
<p>As we continue to refine and expand this system, we're excited about its potential to influence how the broader software community thinks about binary distribution. The combination of Go's compilation speed, Zig's cross-compilation capabilities, and automated CI/CD represents a powerful model for other ecosystems.</p>
<p>The ultimate goal is to create a world where installing and using CLI tools is as simple as possible, regardless of the underlying programming language or system dependencies. This project represents a significant step toward that vision, leveraging the best aspects of Go's compilation speed, Zig's cross-compilation capabilities, and static PIE linking to create truly portable, high-performance, relocatable CLI tools.</p>
<p>We invite the community to engage with this work, contribute improvements, and help us build a more accessible and efficient software distribution ecosystem. Together, we can make powerful CLI tools available to everyone, everywhere, without the traditional barriers of compilation and dependency management.</p>
<h2 id="heading-links">Links:</h2>
<ul>
<li><p><strong>Soar</strong>: <a target="_blank" href="https://github.com/pkgforge/soar">https://github.com/pkgforge/soar</a></p>
</li>
<li><p><strong>Pkgforge-Go</strong>: <a target="_blank" href="https://github.com/pkgforge-go/builder">https://github.com/pkgforge-go/builder</a></p>
</li>
<li><p><strong>Pkgforge-Discord</strong>: <a target="_blank" href="https://discord.gg/djJUs48Zbu">https://discord.gg/djJUs48Zbu</a></p>
</li>
</ul>
<hr />
]]></content:encoded></item><item><title><![CDATA[Cross-Compiling 10,000+ Rust CLI Crates Statically]]></title><description><![CDATA[🤖
AI translation tools were used to assist with language clarity, as our research team are not native English speakers. We believe the quality of our research and findings will speak for themselves


Pkgforge hosts the world's largest collection of ...]]></description><link>https://blog.pkgforge.dev/cross-compiling-10000-rust-cli-crates-statically</link><guid isPermaLink="true">https://blog.pkgforge.dev/cross-compiling-10000-rust-cli-crates-statically</guid><category><![CDATA[Rust]]></category><category><![CDATA[rust lang]]></category><category><![CDATA[Cargo]]></category><category><![CDATA[Rust programming]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[cli]]></category><category><![CDATA[experimentation]]></category><category><![CDATA[scale]]></category><category><![CDATA[automation]]></category><category><![CDATA[Linux]]></category><category><![CDATA[package manager]]></category><dc:creator><![CDATA[Ajam]]></dc:creator><pubDate>Thu, 26 Jun 2025 13:13:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750923596496/4a43954c-6105-4b54-8cc7-5eb857a23c11.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">🤖</div>
<div data-node-type="callout-text">AI translation tools were used to assist with language clarity, as our research team are not native English speakers. We believe the quality of our research and findings will speak for themselves</div>
</div>

<p><a target="_blank" href="https://docs.pkgforge.dev/"><strong>Pkgforge</strong></a> hosts the <a target="_blank" href="https://docs.pkgforge.dev/soar/readme/packages#total">world's largest collection</a> of <a target="_blank" href="https://github.com/orgs/pkgforge/packages">prebuilt</a>, <a target="_blank" href="https://docs.pkgforge.dev/repositories/bincache">static binaries</a> that work everywhere without dependencies. While our <a target="_blank" href="https://docs.pkgforge.dev/repositories">main repos</a> include hand-picked packages and manually maintained by our team, we had an ambitious idea: what if we could automatically harvest CLI tools from ecosystems like Rust's <a target="_blank" href="http://crates.io">crates.io</a>, build them as static binaries, and made them <a target="_blank" href="https://github.com/pkgforge/soar">available to everyone</a>?</p>
<p>Instead of manually curating every package, we decided to tap into existing package ecosystems and automate the entire process. After two weeks of intensive development and countless iterations, we made this idea a reality.</p>
<hr />
<h1 id="heading-ingesting-cratesio">Ingesting Crates.io</h1>
<p>Crates.io provides <a target="_blank" href="https://crates.io/api/openapi.json">api access</a> for individual crate lookups and bulk operations. Initially, our script iterated through the first 1,000 pages (sorted by downloads) with 100 crates per page, yielding approximately 111,000 crates. However, we soon encountered a significant bottleneck: we needed to query each crate individually to determine if it belonged to the <a target="_blank" href="https://crates.io/categories/command-line-utilities"><code>command-line-utilities</code></a>, or produced executables, i.e. contained <a target="_blank" href="https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries"><code>[[bin]]</code></a> in their manifest.</p>
<p>This approach proved impractical as we quickly hit rate limits and potentially violated the <a target="_blank" href="https://crates.io/policies">Usage Policy</a>. Fortunately, <a target="_blank" href="https://rust-lang.github.io/rfcs/3463-crates-io-policy-update.html#data-access">RFC-3463</a> came to our rescue. Crates.io provides periodic database dumps at https://static.crates.io/db-dump.tar.gz . We quickly drafted a <a target="_blank" href="https://github.com/pkgforge-cargo/builder/tree/main/tools/crates-dumper">nifty cli</a> using <a target="_blank" href="https://github.com/dtolnay/db-dump">dtolnay/db-dump</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750926527477/6e5f5128-9e35-45a4-b457-072389900a0c.gif" alt class="image--center mx-auto" /></p>
<p>Then it was just a matter of parsing this with a bit of jq, &amp; automating it via GitHub Actions. Our <a target="_blank" href="https://github.com/pkgforge-cargo/builder/actions/workflows/gen_data.yaml">workflow</a> now generates <a target="_blank" href="https://github.com/pkgforge-cargo/builder/tree/main/data">all the data</a> we will need, automatically.</p>
<hr />
<h1 id="heading-crate-selection">Crate Selection</h1>
<p>Since we ended up with over 111,000 crates, we needed to set some constraints &amp; filter for what we actually wanted to build:</p>
<ol>
<li><p>Should either be of category <a target="_blank" href="https://crates.io/categories/command-line-utilities">command-line-utilities</a>: <code>categories = ["command-line-utilities"]</code></p>
</li>
<li><p>Or must have a <a target="_blank" href="https://doc.rust-lang.org/cargo/reference/cargo-targets.html#binaries"><code>[[bin]]</code></a> section in the <a target="_blank" href="https://doc.rust-lang.org/cargo/reference/manifest.html">Manifest</a>.</p>
</li>
<li><p>Must be updated within the last year, i.e &gt; <code>2024-01-01</code></p>
</li>
</ol>
<pre><code class="lang-bash">🦀 Total crates fetched:            ██████████████████████████████████████████████████ 111,722
     ↓
📦 Crates with binary targets:      ████████████████████████████████  24,658
     ↓
🔧 Crates with CLI category:        ██████████░░░░░░░░░░░░░░░░░░░░░░   8,451
     ↓
📆 Recently updated (2024+):        ███████████░░░░░░░░░░░░░░░░░░░░░  10,033
     ↓ + ↑
✅ Crates to Build: 10,033

// Total crates whose metadata was scraped/fetched: 111,722  
// Total crates with [[bin]] <span class="hljs-keyword">in</span> their Cargo.toml manifest: 24,658  
// Total crates with command-line-utilities category <span class="hljs-keyword">in</span> their Cargo.toml manifest: 8,451  
// After filtering <span class="hljs-keyword">for</span> outdated crates (&gt; date -d <span class="hljs-string">'last year'</span> <span class="hljs-string">'+%Y-01-01'</span>)  
// Total crates to build: 10,033
</code></pre>
<p>We ended up with ~ 10,000 crates that we now planned to compile.</p>
<hr />
<h1 id="heading-build-constraints">Build Constraints</h1>
<p>To achieve truly portable, optimized, and statically linked binaries, we applied the following comprehensive build constraints:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#RUSTFLAGS</span>
[+] Flags: -C target-feature=+crt-static \
           -C default-linker-libraries=yes \
           -C link-self-contained=yes \
           -C prefer-dynamic=no \
           -C embed-bitcode=yes \
           -C lto=yes \
           -C opt-level=3 \
           -C debuginfo=none \
           -C strip=symbols \
           -C link-arg=-Wl,-S \
           -C link-arg=-Wl,--build-id=none \
           -C link-arg=-Wl,--discard-all \
           -C link-arg=-Wl,--strip-all
</code></pre>
<ol>
<li><p><a target="_blank" href="https://rust-lang.github.io/rfcs/1721-crt-static.html"><strong>Statically Linked</strong></a>: <code>-C target-feature=+crt-static</code></p>
</li>
<li><p><a target="_blank" href="https://doc.rust-lang.org/beta/nightly-rustc/rustc_session/config/struct.LinkSelfContained.html"><strong>Self Contained</strong></a>: <code>-C link-self-contained=yes</code></p>
</li>
<li><p><a target="_blank" href="https://doc.rust-lang.org/cargo/reference/features.html"><strong>All Features</strong></a>: <code>--all-features</code></p>
</li>
<li><p><a target="_blank" href="https://doc.rust-lang.org/cargo/reference/profiles.html#lto"><strong>Link Time Optimization</strong></a>: <code>-C lto=yes</code></p>
</li>
<li><p><a target="_blank" href="https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level"><strong>All Optimizations</strong></a>: <code>-C opt-level=3</code></p>
</li>
<li><p><a target="_blank" href="https://doc.rust-lang.org/cargo/reference/profiles.html#strip"><strong>Stripped</strong></a>: <code>-C debuginfo=none -C strip=symbols</code></p>
</li>
<li><p><strong>No System Libraries</strong>: Crates with system library dependencies will fail by design, as we target pure Rust implementations</p>
<blockquote>
<pre><code class="lang-bash"><span class="hljs-comment">#These crates would error out in the following manner</span>
error: could not find system library <span class="hljs-string">'openssl'</span> required by the <span class="hljs-string">'openssl-sys'</span> crate
error: Could not find system library <span class="hljs-string">'sqlite3'</span>
error: pkg-config has not been configured to support cross-compilation
</code></pre>
</blockquote>
</li>
</ol>
<hr />
<h1 id="heading-build-tool">Build Tool</h1>
<p>With over 10,000 crates to build on individual GitHub Actions runners, speed was paramount. While Cargo offers <a target="_blank" href="https://rust-lang.github.io/rustup/cross-compilation.html">cross compilation features</a>, it requires significant setup overhead. We needed a solution that worked out of the box.</p>
<p>Our <a target="_blank" href="https://github.com/pkgforge/devscripts/pkgs/container/devscripts%2Falpine-builder">heavy docker images</a> used for <a target="_blank" href="https://github.com/search?q=repo%3Apkgforge%2Fsoarpkgs%20docker%20run&amp;type=code">official packages</a> consumed 2-3 minutes just for pulling and extraction, making them unsuitable for this scale. This left us with <a target="_blank" href="https://github.com/rust-cross/cargo-zigbuild">rust-cross/cargo-zigbuild</a> &amp; <a target="_blank" href="https://github.com/cross-rs/cross">cross-rs/cross</a>. After some local testing, we decided to use <strong>Cross</strong> as it supported all the targets we needed &amp; worked as advertised: <em>“Zero setup” cross compilation</em></p>
<p>We also used <a target="_blank" href="https://github.com/jpeddicord/askalono">jpeddicord/askalono</a> to automatically detect &amp; copy over licenses.</p>
<pre><code class="lang-bash"><span class="hljs-comment">#The CMD Looks like</span>
cross +nightly build --target <span class="hljs-string">"<span class="hljs-variable">${RUST_TARGET}</span>"</span> -Z unstable-options \
     --all-features \
     --artifact-dir=<span class="hljs-string">"<span class="hljs-variable">${C_ARTIFACT_DIR}</span>"</span> \
     --<span class="hljs-built_in">jobs</span>=<span class="hljs-string">"<span class="hljs-subst">$(($(nproc)</span>+1))"</span> \
     --release \
     --verbose
</code></pre>
<hr />
<h1 id="heading-build-targets">Build Targets</h1>
<p>While <a target="_blank" href="https://github.com/pkgforge/soar"><strong>Soar</strong></a> supports any <strong><em>\</em>Unix-based Distro*</strong>, due to <a target="_blank" href="https://github.com/actions/runner/issues/385">lack of CI support for other Unix Kernel on GitHub Runners</a> (natively, not VMs), we are limited to <strong>Linux</strong> only. We further refined our target matrix by excluding architectures approaching end-of-life:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>HOST_TRIPLET</strong></td><td><strong>RUST_TARGET</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>aarch64-Linux</code></td><td><code>aarch64-unknown-linux-musl</code></td></tr>
<tr>
<td><code>loongarch64-Linux</code></td><td><code>loongarch64-unknown-linux-musl</code></td></tr>
<tr>
<td><code>riscv64-Linux</code></td><td><code>riscv64gc-unknown-linux-musl</code></td></tr>
<tr>
<td><code>x86_64-Linux</code></td><td><code>x86_64-unknown-linux-musl</code></td></tr>
</tbody>
</table>
</div><hr />
<h1 id="heading-build-security">Build Security</h1>
<p>We are aware of issues like <a target="_blank" href="https://github.com/rust-lang/cargo/issues/13897">https://github.com/rust-lang/cargo/issues/13897</a>, so we wanted this to be <a target="_blank" href="https://docs.pkgforge.dev/repositories/soarpkgs/security">as secure as our official repositories</a>, by ensuring:</p>
<ul>
<li><p>Crates are downloaded from <a target="_blank" href="https://crates.io/policies/security">crates.io</a>, like the official <a target="_blank" href="https://github.com/rust-lang/cargo">Cargo</a> does.</p>
</li>
<li><p>CI/CD run on <a target="_blank" href="https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions">GitHub Actions</a>, with temporary, scoped tokens per package</p>
</li>
<li><p>Build Logs are viewable using: <code>soar log ${PKG_NAME}</code></p>
</li>
<li><p>Build Src is downloadable by downloading: <a target="_blank" href="https://github.com/orgs/pkgforge-cargo/packages?tab=packages&amp;q=srcbuild"><code>{GHCR_PKG}-srcbuild-${BUILD_ID}</code></a></p>
</li>
<li><p><a target="_blank" href="https://github.com/pkgforge-cargo/builder/attestations">Artifact Attestation</a> &amp; <a target="_blank" href="https://github.com/pkgforge-cargo/builder/attestations">Build Provenance</a> are created/updated per build.</p>
</li>
<li><p>Checksums are generated (&amp; verified at install time by Soar) for each &amp; every artifact per build.</p>
</li>
</ul>
<p>These measures ensure that even if a malicious crate attempts to compromise the system, its impact is isolated and cannot affect other crates' integrity.</p>
<hr />
<h1 id="heading-build-workflow">Build Workflow</h1>
<p>10,000 multiplied by 4 targets, meant we would need to run ~ 40,000 instances of CI &amp; also handle <a target="_blank" href="https://github.com/pkgforge-cargo/builder/tree/metadata">metadata</a>, <a target="_blank" href="https://github.com/pkgforge-cargo/builder/blob/main/.github/workflows/matrix_builds.yaml">sanity checks</a>, <a target="_blank" href="https://github.com/orgs/pkgforge-cargo/packages?repo_name=builder">uploading to ghcr</a>, all at the same time. We also set up a discord webhook to stream real-time progress updates to our <a target="_blank" href="https://discord.gg/djJUs48Zbu">discord server</a>.</p>
<pre><code class="lang-mermaid">graph TD
  A[🦀 Crates.io API] --&gt;|📊 Scrape Metadata 🧬| B[🔍 Filter &amp; Queue ⏳]
  B --&gt; C[🏗️ GitHub Actions Matrix 🔄]
  C --&gt; D[⚙️ Cross Compiler ⚒️]
  D --&gt; E[📦 Static Binaries 🛠️]
  E --&gt; F[🗄️ GHCR Registry ⬆️]
  F --&gt;|📊 Generate Metadata 🧬| B
  F --&gt; G[🚀 Soar ⬇️]
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750930786349/424400b5-9ba1-41ef-a0b5-f3ec5769eebb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750930888055/3d46d5b7-53f5-4501-8ec1-cea04c153b49.png" alt class="image--center mx-auto" /></p>
<hr />
<h1 id="heading-key-insights-and-findings">Key Insights and Findings</h1>
<h2 id="heading-build-success-vs-failure">Build Success vs. Failure</h2>
<p>We approached this project with optimistic expectations but encountered a sobering reality. Out of approximately 10,000 crates queued for building:</p>
<pre><code class="lang-bash">🏗️ Build Pipeline by Success Rate
────────────────────────────────────────────────────────────────────────
✅ Queued    ████████████████████████████████████████    10,033 (100.0%)
⚙️ Built     ███████████████████████████                  5,779 (57.60%)
❌ Failed    ████████████                                 4,254 (42.40%)
────────────────────────────────────────────────────────────────────────
</code></pre>
<p>So what went wrong? We sampled about 100 of these error logs &amp; concluded:</p>
<ol>
<li><p><strong>System Library Dependencies</strong>: The majority of failures stemmed from crates requiring system libraries that weren't available in our static build environment</p>
</li>
<li><p><strong>Custom Build Systems</strong>: Many crates include <a target="_blank" href="https://doc.rust-lang.org/cargo/reference/build-scripts.html"><code>build.rs</code></a> files that fail when specified dependencies aren't met or when detecting system features during cross-compilation</p>
<pre><code class="lang-bash"> <span class="hljs-comment">#These typically fail cross-compilation</span>
 build.rs files that:
 - Detect system features
 - Link against system libraries
 - Generate code based on target environment
</code></pre>
</li>
</ol>
<p>Despite years of Rust ecosystem maturation, <strong>system library dependencies remain the primary obstacle to universal static compilation</strong>. This reinforces our strategy of targeting CLI tools that can be fully statically linked.</p>
<hr />
<h2 id="heading-crates-vs-executables">Crates vs Executables</h2>
<p>Another interesting insight from building at scale: many crates produce multiple executables. The ~ 5,800 crates we attempted generated ~ 21,000 individual executables (Also referred to as binaries or packages)</p>
<pre><code class="lang-bash">🏗️ Build Pipeline by Executables
──────────────────────────────────────────────────────────────────────────────────
📦 Crates Built       ██████████                                   5,779 (100.0%) <span class="hljs-comment">#Base Line</span>
⚙️ Total Executables  ████████████████████████████████████████     21,042 (364.0%)
──────────────────────────────────────────────────────────────────────────────────
</code></pre>
<p>This 3.6:1 ratio reveals how rich the Rust CLI ecosystem actually is.</p>
<hr />
<h2 id="heading-native-vs-cross">Native vs Cross</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">This counts the executables generated &amp; not individual crates. A single crate may generate multiple executables. (See Above)</div>
</div>

<pre><code class="lang-bash">🏗️ Build Pipeline by Architecture
─────────────────────────────────────────────────────────────────────────────────
🖥️  x86_64-Linux     ████████████████████████████████████████     5,627 (100.00%) <span class="hljs-comment">#Base Line</span>
🖥️  aarch64-Linux    ███████████████████████████████████████▌     5,586 (99.30%)
🖥️  riscv64-Linux    ██████████████████████████████████████▎       5,370 (95.40%)
🖥️ loongarch64-Linux ███████████████████████████████▋              4,459 (79.20%)
─────────────────────────────────────────────────────────────────────────────────
</code></pre>
<p>The consistent success rates across architectures demonstrate Rust's excellent cross-platform story, though newer architectures like loongarch64 show slightly lower compatibility rates. This suggests that architecture-specific code assumptions remain common in the ecosystem.</p>
<p><strong>An interesting anomaly</strong>: Despite building 5,779 crates successfully, x86_64-Linux only shows 5,627 executables. This discrepancy occurs because some crates successfully build for non-standard targets like <code>loongarch64-Linux</code> and <code>riscv64-Linux</code> but fail for standard architectures due to build hooks and scripts that trigger differently across targets.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750942440242/8809f2bd-ea27-410c-8b4f-3edbbae332a2.gif" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750943280327/83353900-4b76-464a-90fb-043df81dea76.png" alt class="image--center mx-auto" /></p>
<p>You can explore detailed per-target build results here: <a target="_blank" href="https://github.com/pkgforge-cargo/builder/blob/main/data/CRATES_BUILT.json">CRATES_BUILT.json</a></p>
<hr />
<h2 id="heading-ci-performance-metrics">CI Performance Metrics</h2>
<p>Our primary build workflow (<a target="_blank" href="https://github.com/pkgforge-cargo/builder/actions/workflows/matrix_builds.yaml">matrix_builds.yaml</a>) <a target="_blank" href="https://github.com/pkgforge-cargo/builder/actions/workflows/matrix_builds.yaml">handles the bulk</a> of compilation, with additional workflows managing metadata and miscellaneous tasks. As we implement incremental builds (only rebuilding updated crates) and caching strategies, these metrics will improve significantly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750941666650/9984d3d9-62a8-4022-9a92-949dafef6d74.png" alt class="image--center mx-auto" /></p>
<p>Average build time was ~ 2 minutes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750941742936/0525d73a-d318-4dbc-989e-2f4c97e92a9c.png" alt class="image--center mx-auto" /></p>
<hr />
<h1 id="heading-reviewhttpsgithubcompkgforge-cargobuilderactionsworkflowsgithubworkflowsmatrixbuildsyaml"><a target="_blank" href="https://github.com/pkgforge-cargo/builder/actions/workflows/.github/workflows/matrix_builds.yaml"><strong>Review</strong></a></h1>
<h2 id="heading-compilation-vs-prebuilt-distribution">Compilation vs. Prebuilt Distribution</h2>
<p>Compilation will always be slower than fetching prebuilt binaries, but the degree varies significantly based on crate complexity and dependency count. For our demonstration, we'll use <a target="_blank" href="https://github.com/sharkdp/fd">fd-find</a> as a r<a target="_blank" href="https://github.com/sharkdp/fd">epresen</a>tative example, though your experience may vary with more dependency-heavy crates.</p>
<p><em>Note: We're not measuring CPU, disk, memory, or bandwidth usage here—try it yourself to experience the full performance difference.</em></p>
<h3 id="heading-cargo">Cargo</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750937455194/aeaee723-4af5-4c95-8a31-50f4001c26ba.gif" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">$ time cargo install fd-find

real    0m51.893s
user    3m36.568s
sys     0m24.411s
</code></pre>
<h3 id="heading-cargo-binstallquick-install">Cargo Binstall/Quick Install</h3>
<p><a target="_blank" href="https://github.com/cargo-bins/cargo-binstall">Cargo Binstall</a> <a target="_blank" href="https://github.com/cargo-bins/cargo-binstall">leverages preb</a><a target="_blank" href="https://github.com/cargo-bins/cargo-quickinstall/">uilt binaries</a>, <a target="_blank" href="https://github.com/cargo-bins/cargo-quickinstall/"></a>though it requires time for crate resolution: <a target="_blank" href="https://github.com/cargo-bins/cargo-binstall/issues/1333">related issue</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750938339595/6094bebb-70c5-43dd-9c35-dff74a3b6a80.gif" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">$ time cargo binstall fd-find --no-confirm

real    0m6.001s
user    0m0.118s
sys     0m0.083s
</code></pre>
<p><a target="_blank" href="https://github.com/cargo-bins/cargo-binstall"><strong>Cargo-Binstall</strong></a> and <a target="_blank" href="https://github.com/cargo-bins/cargo-quickinstall/"><strong>Cargo-Quickinstall</strong></a> are excellent tools that:</p>
<ul>
<li><p>Integrate with <code>cargo install</code> workflow</p>
</li>
<li><p>Handle development dependencies and features</p>
</li>
<li><p>Target developers who want faster <code>cargo install</code></p>
</li>
</ul>
<p><a target="_blank" href="https://github.com/pkgforge/soar"><strong>Soar</strong></a> takes a different approach:</p>
<ul>
<li><p><strong>Distribution-focused</strong>: Static executables for end users</p>
</li>
<li><p><strong>No development integration</strong>: Not meant for <code>cargo</code> workflows</p>
</li>
<li><p><strong>Dependency-free</strong>: Zero system library requirements</p>
</li>
<li><p><strong>Cross-distribution</strong>: Works on any *nix system (MUSL/GLIBC)</p>
</li>
</ul>
<h3 id="heading-soar">Soar</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750937721483/9b7113d7-67f7-4786-b6dc-712b185f461d.gif" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash"><span class="hljs-comment">#Soar uses pkg_ids to ensure exact match because we have too many packages</span>
$ time soar install <span class="hljs-string">"fd#pkgforge-cargo.fd-find.stable:pkgforge-cargo"</span>

real    0m1.695s
user    0m0.062s
sys     0m0.090s
</code></pre>
<hr />
<h1 id="heading-conclusion">Conclusion</h1>
<p>This project represents more than just a build farm; it's a proof of concept &amp; also a reality check for the whole ecosystem.</p>
<h2 id="heading-key-discoveries-and-implications">Key Discoveries and Implications</h2>
<p><strong>The Rust CLI ecosystem is remarkably rich and diverse.</strong> Our 3.6:1 ratio of executables to crates reveals that the community is building comprehensive toolsuites rather than single-purpose utilities. This multiplier effect means that successfully building even a subset of available crates provides exponentially more value to end users.</p>
<p><strong>Cross-compilation compatibility has room for improvement.</strong> While Rust's cross-platform story is generally excellent, our 42.4% failure rate highlights that system library dependencies and architecture-specific assumptions remain significant obstacles. This suggests opportunities for the community to develop more portable alternatives to system library bindings.</p>
<p><strong>Static linking is both powerful and challenging.</strong> The ability to produce truly portable binaries that work across any Linux distribution without dependencies is transformative for CLI tool distribution. However, achieving this requires careful consideration of build flags, dependencies, and compilation strategies.</p>
<h2 id="heading-broader-ecosystem-implications">Broader Ecosystem Implications</h2>
<p>Our work demonstrates that automated, large-scale binary distribution is not only feasible but can provide significant value to the developer community. The time savings alone—from nearly a minute of compilation time to under two seconds of download time—represent a meaningful improvement in developer productivity.</p>
<p>More importantly, this approach democratizes access to CLI tools. Users no longer need to have Rust installed, understand compilation flags, or debug dependency issues. They can simply install and use tools, lowering the barrier to entry for adopting Rust-based CLI utilities.</p>
<hr />
<h1 id="heading-future-roadmap">Future Roadmap</h1>
<p>The <a target="_blank" href="https://github.com/pkgforge-cargo/builder/">pkgforge-cargo</a> project will likely see these additions/improvements in the near future:</p>
<ul>
<li><p><strong>Automated updates</strong>: Rebuild crates when new versions are published (this is partially implemented)</p>
</li>
<li><p><strong>Integration with Cargo</strong>: Maybe something similar to what `cargo binstall` does.</p>
</li>
<li><p><strong>Build optimization</strong>: Optimize CI Build times &amp; reduce Failures</p>
</li>
<li><p><strong>Contribute Upstream</strong>: Opt-in system to automatically create GitHub issues with build logs when crate compilation fails, helping maintainers improve cross-compilation compatibility</p>
</li>
<li><p><strong>Community Feedback</strong>: Listen to our users &amp; the community to improve this project &amp; hope for a <a target="_blank" href="https://docs.pkgforge.dev/repositories/soarpkgs/re-distribution">widespread adoption beyond Soar</a>.</p>
</li>
</ul>
<p>As we continue to refine and expand this system, we're excited about its potential to influence how the broader software community thinks about binary distribution. The lessons learned here apply beyond Rust to any compiled language ecosystem, and we're eager to explore applications in Go, Zig, and other emerging systems languages. (Help us if you can)</p>
<p>The ultimate goal is to create a world where installing and using CLI tools is as simple as possible, regardless of the underlying programming language or system dependencies. This project represents a significant step toward that vision, and we're committed to continued innovation in this space.</p>
<p>We invite the community to engage with this work, contribute improvements, and help us build a more accessible and efficient software distribution ecosystem. Together, we can make powerful CLI tools available to everyone, everywhere, without the traditional barriers of compilation and dependency management.</p>
<h2 id="heading-links">Links:</h2>
<ul>
<li><p><strong>Soar</strong>: <a target="_blank" href="https://github.com/pkgforge/soar">https://github.com/pkgforge/soar</a></p>
</li>
<li><p><strong>Pkgforge-Cargo</strong>: <a target="_blank" href="https://github.com/pkgforge-cargo/builder">https://github.com/pkgforge-cargo/builder</a></p>
</li>
<li><p><strong>Pkgforge-Discord</strong>: <a target="_blank" href="https://discord.gg/djJUs48Zbu">https://discord.gg/djJUs48Zbu</a></p>
</li>
</ul>
<hr />
]]></content:encoded></item><item><title><![CDATA[Bootstrapping Soar on HTTP-Only Bare/Legacy Systems]]></title><description><![CDATA[Practical /dev/tcp in the HTTPS Era
Getting Soar onto systems with no download tools is a chicken-and-egg problem. Fresh containers, minimal distributions, and legacy Unix systems often lack curl, wget, or even working SSL libraries. You need a tool ...]]></description><link>https://blog.pkgforge.dev/https-via-http</link><guid isPermaLink="true">https://blog.pkgforge.dev/https-via-http</guid><category><![CDATA[tips]]></category><category><![CDATA[tricks]]></category><category><![CDATA[Linux]]></category><category><![CDATA[http]]></category><category><![CDATA[proxy]]></category><dc:creator><![CDATA[Ajam]]></dc:creator><pubDate>Mon, 02 Jun 2025 13:20:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748870328486/20e9fefd-6262-4de8-a0a9-0a3d5c6d4ecf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-practical-devtcp-in-the-https-era">Practical /dev/tcp in the HTTPS Era</h1>
<p>Getting <a target="_blank" href="https://github.com/pkgforge/soar">Soar</a> onto systems with no download tools is a chicken-and-egg problem. Fresh containers, minimal distributions, and legacy Unix systems often lack curl, wget, or even working SSL libraries. You need a tool to get tools.</p>
<h2 id="heading-the-challenge">The Challenge</h2>
<p>Consider these scenarios:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Fresh Debian container</span>
$ docker run -it debian:latest
<span class="hljs-comment"># No curl, no wget, no ca-certificates</span>

<span class="hljs-comment"># Legacy system</span>
$ uname -a
<span class="hljs-comment"># SunOS legacy 5.10 Generic_147441-01 i86pc i386 i86pc</span>
$ <span class="hljs-built_in">which</span> curl wget
<span class="hljs-comment"># command not found</span>

<span class="hljs-comment"># No Privileges</span>
$ apt install curl
Error: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
Error: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?
</code></pre>
<p>You need to download Soar, but you can't download Soar without download tools. Traditional solutions fail:</p>
<ul>
<li><p><code>apt install curl</code> requires privileges and a working package manager</p>
</li>
<li><p>Copying files requires existing access/infrastructure or is just too slow over scp</p>
</li>
<li><p>Building from source needs compilers and dependencies</p>
</li>
</ul>
<h2 id="heading-the-solution">The Solution</h2>
<p>Every system with bash has <code>/dev/tcp</code> - a built-in feature for raw TCP connections.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">⚠</div>
<div data-node-type="callout-text">Bash must be compiled with<code>--enable-net-redirections</code>,but this is by default always enabled.</div>
</div>

<p>No external dependencies, no SSL requirements, just basic HTTP over TCP:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#From: https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet?tab=readme-ov-file#4vii-file-download-without-curl</span>
<span class="hljs-function"><span class="hljs-title">burl</span></span>() {
    IFS=/ <span class="hljs-built_in">read</span> -r proto x host query &lt;&lt;&lt;<span class="hljs-string">"<span class="hljs-variable">$1</span>"</span>
    <span class="hljs-built_in">exec</span> 3&lt;&gt;<span class="hljs-string">"/dev/tcp/<span class="hljs-variable">${host}</span>/<span class="hljs-variable">${PORT:-80}</span>"</span>
    <span class="hljs-built_in">echo</span> -en <span class="hljs-string">"GET /<span class="hljs-variable">${query}</span> HTTP/1.0\r\nHost: <span class="hljs-variable">${host}</span>\r\n\r\n"</span> &gt;&amp;3

    <span class="hljs-comment">#Skip headers until we hit the empty line</span>
    <span class="hljs-keyword">while</span> <span class="hljs-built_in">read</span> -r line &lt;&amp;3; <span class="hljs-keyword">do</span>
        <span class="hljs-comment"># Remove carriage return and check if line is empty</span>
        line=<span class="hljs-variable">${line%$'\r'}</span>
        [[ -z <span class="hljs-string">"<span class="hljs-variable">$line</span>"</span> ]] &amp;&amp; <span class="hljs-built_in">break</span>
    <span class="hljs-keyword">done</span>

    <span class="hljs-comment">#Output only the body</span>
    cat &lt;&amp;3
    <span class="hljs-built_in">exec</span> 3&gt;&amp;-
}

<span class="hljs-comment">#Examples:</span>
burl <span class="hljs-string">"http://http.pkgforge.dev/https://ip.pkgforge.dev/json"</span>
burl <span class="hljs-string">"http://http.pkgforge.dev/https://github.com/pkgforge/soar/releases/latest/download/soar-x86_64-linux"</span> &gt; <span class="hljs-string">"./soar"</span>
</code></pre>
<p>This works on any bash system, but GitHub serves HTTPS. Legacy systems can't connect to HTTPS endpoints.</p>
<p>This works in:</p>
<ul>
<li><p>Fresh Docker containers (<code>debian:latest</code>)</p>
</li>
<li><p>Legacy Unix systems without SSL</p>
</li>
<li><p>Minimal environments with only bash</p>
</li>
<li><p>Systems with broken certificate stores</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🕸</div>
<div data-node-type="callout-text"><a target="_self" href="http://http.pkgforge.dev">http://http.pkgforge.dev</a> will not open in your browser.</div>
</div>

<h2 id="heading-the-http-to-https-proxy-bridge">The HTTP-to-HTTPS Proxy Bridge</h2>
<p>The solution: an HTTP proxy that handles HTTPS termination. A Cloudflare Worker accepts HTTP requests and forwards them to HTTPS destinations:</p>
<p><code>Client (HTTP) → Worker (HTTP) → Target (HTTPS) → Worker → Client</code></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Extract target URL from path</span>
<span class="hljs-keyword">const</span> destUrl = url.pathname.substring(<span class="hljs-number">1</span>);

<span class="hljs-comment">// Forward to HTTPS endpoint</span>
<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(destUrl, {
  <span class="hljs-attr">method</span>: request.method,
  <span class="hljs-attr">redirect</span>: <span class="hljs-string">'follow'</span>,
  <span class="hljs-attr">headers</span>: cleanHeaders(request.headers)
});

<span class="hljs-keyword">return</span> response;
</code></pre>
<h2 id="heading-edge-cases">Edge Cases</h2>
<p>The code of worker resides @<a target="_blank" href="https://github.com/pkgforge-dev/reverse-proxies/blob/main/http.pkgforge.dev/worker.js">https://github.com/pkgforge-dev/reverse-proxies/blob/main/http.pkgforge.dev/worker.js</a> &amp; handles several edge cases for compatibility:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#From a system that has curl, you can read the help page</span>
$ curl -qfsSL <span class="hljs-string">"http://http.pkgforge.dev/help"</span>
<span class="hljs-string">'
This is a reverse proxy that works over HTTP (also HTTPS) to proxy to HTTPS sites.
For example, if you are on an ancient system with no SSL and only bash,
you can use this to download a static curl binary &amp; join the modern internet.

Simply append your URL to http://http.pkgforge.dev/$URL
Example, http://http.pkgforge.dev/https://example.com --&gt; Requests example.com (HTTPS) --&gt; Returns the Response Back
If you want to use the DNS or IP Address to access this proxy, then visit the endpoints below.
Each endpoint will print a template HTTP request (with bash /dev/tcp example).

If your client has DNS, visit: http.pkgforge.dev/self-dns
If your client has IPv4, visit: http.pkgforge.dev/self-ipv4
If your client has IPv6, visit: http.pkgforge.dev/self-ipv6

Source Code: https://github.com/pkgforge-dev/reverse-proxies/tree/main/http.pkgforge.dev
Contact: https://docs.pkgforge.dev/contact/chat
'</span>
</code></pre>
<p><strong>DNS-less clients</strong>: Provides IPv4/IPv6 endpoints for systems without DNS resolution:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Use IP directly if DNS is broken</span>
burl <span class="hljs-string">"http://172.67.74.226/https://github.com/..."</span>
</code></pre>
<p><strong>Header management</strong>: Strips problematic headers that interfere with proxying:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Clean headers for forwarding</span>
requestInit.headers.delete(<span class="hljs-string">'host'</span>);
requestInit.headers.delete(<span class="hljs-string">'connection'</span>);
</code></pre>
<p><strong>Redirect handling</strong>: Follows redirects automatically since GitHub releases often redirect to CDN URLs.</p>
<h2 id="heading-real-world-usage">Real-World Usage</h2>
<p>This is used in Soar's <a target="_blank" href="https://github.com/pkgforge/soar/blob/main/install.sh">official installer</a>:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Fallback for systems without download tools</span>
<span class="hljs-keyword">if</span> ! <span class="hljs-built_in">command</span> -v curl &gt;/dev/null &amp;&amp; ! <span class="hljs-built_in">command</span> -v wget &gt;/dev/null; <span class="hljs-keyword">then</span>
  raw_http_get <span class="hljs-string">"http://http.pkgforge.dev/https://github.com/pkgforge/soar/releases/latest/download/soar-<span class="hljs-variable">${ARCH}</span>"</span> &gt; <span class="hljs-string">"./soar"</span>
  sed <span class="hljs-string">"1,/^\r\{0,1\}$/d"</span> -i <span class="hljs-string">"./soar"</span>
<span class="hljs-keyword">fi</span>
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">ℹ</div>
<div data-node-type="callout-text">We have added quite a lot of fallbacks in the script, the bash /dev/tcp being only one of those. We recommend reading the rest yourself &amp; trying some of them.</div>
</div>

<h2 id="heading-why-this-matters">Why This Matters</h2>
<p>Soar needs to run on diverse systems - from cutting-edge containers to decades-old Unix boxes. Traditional package managers assume modern tooling exists. This bootstrap method ensures Soar can install itself anywhere bash runs.</p>
<p>Once Soar is installed, it handles all future downloads with proper SSL, certificate validation, and modern HTTP features. The proxy is just for the initial bootstrap.</p>
<h2 id="heading-security-trade-offs">Security Trade-offs</h2>
<p>The proxy breaks end-to-end encryption for the bootstrap download. This is acceptable because:</p>
<ul>
<li><p>Soar releases are public binaries</p>
</li>
<li><p>Checksums can be verified after download</p>
</li>
<li><p>It's only used when no secure alternatives exist</p>
</li>
<li><p>The alternative is manual file copying or no access at all</p>
</li>
</ul>
<p>For production usage, Soar uses proper HTTPS connections.</p>
<h2 id="heading-beyond-soar">Beyond Soar</h2>
<p>This technique works for any static asset like webpages or files that needs to reach legacy systems:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Get any GitHub release</span>
burl <span class="hljs-string">"http://http.pkgforge.dev/https://github.com/user/repo/releases/latest/download/binary-linux-amd64"</span>

<span class="hljs-comment"># Public package repositories</span>
burl <span class="hljs-string">"http://http.pkgforge.dev/https://packages.example.com/tool.tar.gz"</span>
</code></pre>
<p>The proxy solves the fundamental bootstrap problem: getting the first tool onto a system so it can get better tools.</p>
<p>The complete proxy runs as a Cloudflare Worker, handling the HTTPS complexity while presenting a simple HTTP interface to legacy clients. Source code and deployment instructions are available in the <a target="_blank" href="https://github.com/pkgforge-dev/reverse-proxies/tree/main/http.pkgforge.dev">reverse-proxies repository</a>.</p>
<p>This architectural approach prioritizes compatibility over security for the narrow use case of system bootstrapping, enabling modern tools to run on systems that predate modern web infrastructure.</p>
<h2 id="heading-references-amp-further-reading">References &amp; Further Reading</h2>
<ul>
<li><p><a target="_blank" href="https://rednafi.com/misc/http_requests_via_dev_tcp/">https://rednafi.com/misc/http_requests_via_dev_tcp/</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/fijimunkii/bash-dev-tcp">https://github.com/fijimunkii/bash-dev-tcp</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet">https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet</a></p>
</li>
<li><p><a target="_blank" href="https://www.gnu.org/software///bash/manual/bash.html">https://www.gnu.org/software///bash/manual/bash.html</a></p>
</li>
<li><p><a target="_blank" href="https://tldp.org/LDP/abs/html/devref1.html">https://tldp.org/LDP/abs/html/devref1.html</a></p>
</li>
<li><p><a target="_blank" href="https://ivanmosquera.net/2024/08/27/network-tools-inside-a-pod-exploring-dev-tcp-and-busybox/?utm_source=chatgpt.com">https://ivanmosquera.net/2024/08/27/network-tools-inside-a-pod-exploring-dev-tcp-and-busybox/?utm_source=chatgpt.com</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>