Hacker News new | ask | show | jobs
by chatmasta 1235 days ago
I'm really not a fan of the "download the prebuilt binary from github releases" workflow that's been proliferating along with the popularity of Rust. It seems like a step backward in terms of secure package management, and it's surprising to me that Rust doesn't offer a more out-of-box experience for this, instead encouraging users to build from source. I understand the arguments for this, and I even find some of them convincing - namely, that the inverse problem of opaque intermediate binaries and object files would be much worse as it would cause a cascade of brittle builds and barely any packages would work.

But the fact remains that end users want to download a binary, and the common approach to this is to simply publish them to GitHub actions. Surely Cargo could offer a better option than this, while retaining the ability to build all packages from source (maybe you can only publish binaries to Cargo _in addition_ to the source files... or maybe Cargo.toml could include a link to GitHub releases, and Cargo could include a command for downloading directly from there.)

In the meantime, I've been considering publishing Rust binaries to npm (in addition to GitHub releases). I got the idea from esbuild, which is written in Go but distributed via npm. What do people think of this approach? Here's a recent blog post [0] describing the setup.

[0] https://blog.orhun.dev/packaging-rust-for-npm/

6 comments

I've noticed people publishing binaries to PyPI too - you can run "pip install ziglang" to get Zig, for example.

I wrote a bit about that pattern here: https://simonwillison.net/2022/May/23/bundling-binary-tools-...

we actually agree and are working on this! github releases are just an easy initial target, and makes our tool a drop-in replacement for the kinds of things people are already doing. longer-term we'd like to see something more robust, and cargo-dist is the first cog in that machine.

i have personally packaged and published many rust devtools on npm (cloudflare's wrangler, apollo's rover, wasm-pack) but that was largely because they were targeted at a javascript developer audience.

as a former npm registry engineer i'm curious what you find to be the particular value of publishing to npm? installing node is actually very unpleasant and then getting global installs to work is also... very unpleasant. i think it works well for people already in that ecosystem but i think we can build something better for a more agnostic audience that can give a similar out-of-box exp without requiring a centralized registry. would love to learn more about your perspective!

> as a former npm registry engineer i'm curious what you find to be the particular value of publishing to npm

I have to admit I find this to be an amusing sentence. :D Poor npm (maybe rightfully) does not have the best reputation.

I suppose it appeals to me mostly for reasons of personal bias, and the thought that most people downloading binaries from GitHub probably have node installed. Although I'm probably wrong about that. I also like that optionalDependencies and postinstall steps can use JS code to effectively act as an install script, which at least feels somewhat cleaner than curl install.sh | bash.

You make a good point about this being more appropriate for binaries that have some relation to JS (like esbuild). I think this is probably a compelling enough argument not to distribute binaries to npm if they're not related to JS - or at least, if there is no obvious overlap between the expected userbase of the binary and JS users.

Perhaps the solution friendliest to end users (but least friendly to maintainers) would be to distribute the binary to as many package managers as possible. I mean, why not publish it to npm, and PyPi, and maven, and rubygems...? If your Rust tool has bindings in these languages, then of course it makes sense. Otherwise, it sounds ridiculous... but is it really so different from publishing to multiple OS-level package managers like apt, brew, macports, etc? Almost certainly your users, if they're downloading a tool from GitHub, will have one of these package managers installed. (But then again they'll probably also have one of apt/brew/nix, so maybe no need to use the language specific manager.)

Actually, if this is something you're working on, maybe that is a problem you can solve - you could handle distributing the binary to multiple package registries, and I could just push it to GitHub releases and add an extra line to my workflow.yml. You wouldn't even need to store the binaries - you could just fetch them from the GitHub releases page. (Although now we've strayed quite far from my original motivation of a more secure distribution channel! And perhaps this leads to reinventing a few wheels...)

> most people downloading binaries from GitHub probably have node installed

There are millions, perhaps even billions of people who aren't js developers.

I'm one of them :)

Worth considering using nix with cargo. Of course it still involves a lot of "download from github" or "download from nix cache" but reproducibility + tight source hash pinning helps guarantee provenance.
> It seems like a step backward in terms of secure package management

what is an example of a language package manager that does this well, in your view? I think the idea is something similar to how apt-get/deb/rpm work at the os-level, but I'm interested in the details of what the improved version of this is in your mind.

Github's CI is a fine way to build binaries.

Github's CDN is a fine way to host binaries in a highly available manner which is also not easy to tamper with.

GitHub's project page gives instant access to source code, and to a rich README.

I don't see how Github in this regard is any worse than npm or pypi.

What I would appreciate is a way to sign binaries the same way commits are signed, attesting that it was built from a particular commit, and a particular state of dependencies, by a compiler isolated from the internet. GitHub's CI runner might sign it with some private key, while a public key to check signatures would be available from github.com.

Of course that would require some cooperation from code authors, but for important code that should be manageable.

with npm:

    $ npm install foo # or
    $ npx foo
with github:

    Find repository
    Click latest release, downloads to ~/Downloads
    $ tar -xvzf ~/Downloads/some.tar.gz
    $ cp foo/bin/foo /usr/local/bin
As clearly laid out in the article, the rust equivalent to npm install is

    cargo install foo

The entire point of providing downloads is for people who don't have dev tools already installed.
How is distributing binaries via cargo (automatic, can’t opt out, not possible to audit, invisible) better than explicitly downloading them from github?

Just puzzled; I think binary distributions make any supply chain issues basically impossible to solve.

Vendoring them into the tool chain instead of distributing source code you can compile yourself seems the opposite of solving the problem you’ve posed.