Can you name anything notable in Rust besides firefox internals off the top of your head? swhkd comes to mind in light of recent CVE series..
It looks like fans like Rust, but not many people actually want to use it, so they rewrite random stuff, so maybe others will notice it somehow and start using it.
> Several components of the Dropbox core file-storage system were written in Rust as one step in part of a larger project to pursue greater datacenter efficiency. It’s currently used by all Dropbox storage today, serving >500 million users.
> Figma Our real-time multiplayer syncing server (used to edit all Figma documents) is written in Rust.
> npm, Inc - Replacing C and rewriting performance-critical bottlenecks in the registry service architecture.
> OVH - We used Rust to build a high performance, highly available log management system.
> QCERT (Qatar's National CERT) - DNS log analysis pipeline entirely written in rust, running on top of our own Rust stream processing platform.
> 1Password - We use Rust to power the entire backend (encryption, networking, database, and business logic) of all our client apps.
> Fire and Emergency NZ - The New Zealand Fire Service is using a custom geolocation search engine, built in rust, that runs on embedded hardware within a fire truck to stream hazard information to a fire crew at an incident.
> Deliveroo - We are using Rust to quickly make assignment decisions in our food delivery network.
> System76 - As a Linux-based computer-manufacture, much of our infrastructure and desktop Linux projects are written in Rust. From hardware certification, flashing, and imaging; to system services and GTK3 desktop applications.
> Canonical - Everything from server monitoring to middleware!
> Cloudflare - We are using Rust as a replacement for memory-unsafe languages (particularly C) and are using it in our core edge logic.
I use ripgrep all the time, and it's written in Rust, although I wouldn't give a flying shit if it was written in C, Go, or C++. It's just a real solid piece of software.
Well, it’s quite a departure. rg builds on grep’s foundation and is a good CLI citizen, and ugrep offers a TUI and bells and whistles and a whole DSL to filter out files and run iconv on them… I’m unsure. It’s like giving me a car because I need a reading light. Would disrupt my usual workflows, while rg just displaced grep organically.
I’m quite wary of jq for the reason that usually I don’t need it often enough to learn its language. That would be another piece of software like this.
Sorry for picking this particular project to air my gripes – it's no worse than others. But here's something that's been annoying me a lot with Rust projects (a language and ecosystem that I love): The software lists a very small set of dependencies, but then when you actually go and take a look in Cargo.toml, it actually has a shitton of dependencies. The fact that these are "magically handled" by Cargo does not make them non-dependencies! The culture of pretending that only non-Rust deps are deps is incredibly annoying and unproductive.
*Edit based on lots of replies:* Before writing a reply that starts out with assuming that my comment says anything negative about having dependencies, or having lots of them, please take a moment to consider what I'm actually saying. This post is not a critique of dependencies, nor a critique of lots of depdendencies. It's a critique of pretending that only some dependencies are dependencies.
Hi, I would like to know what's wrong with a lot of dependencies? One disadvantage I know is long compile time and maybe a little larger binary size, but I don't think it's too bad.
You're doing that by running the guy's project in the first place, even if it had no dependencies whatever. I'm tired of this being brought up like it's specific to some NPM package or some guy's Rust project.
Sorry, but running code you didn't write yourself is a fact of life to whose risk you will have to reconcile yourself, if you want to benefit from an extraordinary patrimony of code that no one person could write in a million years.
Reducing the risk of malicious code is a good goal, yes. Reducing the number of all - including transitive - dependencies may be a fair way to do that. It really depends on the context of the system you're developing: is it running on users' machines, is it a critical part of the system, can it access important data, etc etc. It's certainly good to think about how to reduce supply chain risk - and that may begin with thinking about dependencies, but it certainly shouldn't end there.
> It's certainly good to think about how to reduce supply chain risk - and that may begin with thinking about dependencies, but it certainly shouldn't end there.
I was responding to "striving to reduce the number of dependencies is a good goal". I don't think that's categorically true. I think it's an XY problem where one would do better to focus on the 'X' (i.e. reducing risk of malicious third-party code).
I agree with you, you're not wrong, but the people who use this argument are not arguing pragmatically. I believe this the "no dependency" argument is used by folks who want to virtue signal that they are "real programmers" because they don't use dependencies (ignore the kernel and all the drivers in it!!!) and instead use 100% stand-alone "free" software.
Yeah, I'm sorry you're being downvoted. I totally agree and I'll sign myself up for getting downvoted too. There's nothing I hate more than cargo-cult programming and cargo-cult thinking, which always takes the form of these unthinking quarter-correct maxims like "dependencies are bad!", or "state in your server is bad!", or "O(1) algorithms are better than O(n) - so use my algorithm that achieves constant time by iterating over everything in the known universe!".
It's not just not thinking pragmatically, it's not thinking tout court. It's a thought-terminating cliché. It's trying to reduce problem X to universal solution Y because you don't trust yourself to genuinely think it through. It's the programming equivalent of Reddit neckbeards who regurgitate (semi-accurate) names of logical fallacies from Wikipedia rather than actually evaluating the other person's argument.
> You're doing that by running the guy's project in the first place, even if it had no dependencies whatever
Running a naive "cargo tree" on this project tells me I'm now also trusting about 80 other projects besides this persons project. Including a Wayland client? And a "Scoped Thread Local Storage" implementation? For a sysctl replacement?
And a lot more than that! You'll be trusting: a load of silently-linked dylibs; some guy called Linus; some thing called GCC or LLVM (gosh, you don't get that with C); some weird packages called libc and crt0 and shit like that - and much much more besides.
It's almost as if "a sysctl replacement?!?" is necessarily built on an extremely complex edifice of code, due to how modern computers work, which can be hidden (cf: dynamic linking) but not avoided. ;)
(Less facetiously: Yes, if you start thinking through, from first principles, all the machine code which has to run in order for this tool to function on an acceptable range of computers, you can then start to grapple with the real problem, which is unfortunately more complex than "how many Rust crates does `cargo tree` output?".)
Sure, it's a problem that needs to be solved on all layers. So why shouldn't application programmers take their part of the responsibility? Is that how it works? Other people also have problems, so I don't need to solve mine?
In other words, there is a quantitative risk difference between depending on two external libraries (particularly if you pick well-vetted ones) vs. depending on 15000 libraries like some node projects.
Every additional library your build brings in, adds a small additional amount of supply chain risk.
So it's not about trying to be hardline about not depending on anything, but if you want to minimize risk you'd want to curate carefully which libraries you bring in.
I don't think you can compare the rust dependencies and #leftpad.
Crates.io don't allow to remove packages. Also dependencies don't tend to be 10 lines of code only
Every dependency is a potential point of failure, and a security risk. It requires you to trust every dependency entirely. This could be problematic for tools like this, that run very high permission operations.
The code you write may equally be a security risk. Consider the proverbs which caution against rolling your own crypto, for an extreme example. Consider also the potential security issues with rolling your own OAuth or similar. Moreover, there are probably lots of other bugs to be avoided by taking on dependencies—consider the fraught domain of text rendering as an extreme example. These are competing concerns which must be weighed carefully. Trite advice like “minimize dependencies” is just as bad as “don’t rewrite it yourself”. I don’t think there are any easy answers here.
> Hi, I would like to know what's wrong with a lot of dependencies?
I'm not saying that there's necessarily anything wrong with a lot of dependencies. It can be, but that's a separate discussion. What I'm saying is that it's wrong to pretend that you don't have a lot of dependencies when you actually do.
Ah I think there was miscommunication due to mental biases. Like I misunderstood your objection, you probably misunderstood the docs. I don't think the author is pretending anything. The docs says that it depends on procfs to highlight it as the main dependency or maybe the odd one.
In Rust community, it's a common knowledge that 1. If it's a high level tool, it will have multiple dependencies, and 2. The actual dependency list will be auto generated by the package managers (cargo or os) and be pinned in every release, available publicly.
Security risks, faster deprecation, and less flexibility.
If another dependency changes it's api, you immediately have a problem. Your answer may be to fix the version to a static value abd forget about it - but if a security vulnerability is found in that dependency afterward, what do you do? You probably won't even catch it.
Because you need to audit every dependency along with your code when looking for defects. A huge list of dependencies, especially ones that include their own dependencies, makes this an overwhelming task.
It also sucks bigtime when you're trying to install on non-internet connected machines.
> The culture of pretending that only non-Rust deps are deps is incredibly annoying and unproductive.
The reason that projects usually only list the non-Rust deps in their readme is because these need to be installed manually by the user in order to build or run the piece of software in question.
There would be no point in listing all direct and indirect crates that a project depends on in the readme, since that list is already in Cargo.lock anyway which is meant to also be committed.
Really don’t see any reason for this particular objection.
> The reason that projects usually only list the non-Rust deps in their readme is because these need to be installed manually by the user in order to build or run the piece of software in question.
I understand that. It's almost spelled out in my comment. But the ones that can be automatically installed by Cargo are still dependencies.
> There would be no point in listing all direct and indirect crates that a project depends on in the readme, since that list is already in Cargo.lock anyway which is meant to also be committed.
I know. But this should at the very least be acknowledged.
> Really don’t see any reason for this particular objection.
It's entirely reasonable for someone not to want tooling to automatically grab dependencies from the internet. Such people need to know which dependencies they need to provide.
>Such people need to know which dependencies they need to provide.
Cargo.lock specifies exactly which dependencies are required and in which version (down to git commit hashes and checksums). You can parse that file, way less error prone that doing it by hand (you can probably even fully automate the process of checking out the dependency repos).
I see no reason why library authors should be expected to document this when the actual source of truth — the Cargo.toml file — is sitting right there and will never be wrong. If you want to see the transitive dependencies, all you need is to run "cargo tree".
Both crates.io and lib.rs surface this automatically right there on the crate's page.
The rust "culture" on transitive dependencies is actually laudably transparent: it's built right into the tools.
I mean, the number of dependencies a node project uses doesn't really affect me. If they have 1 or if they have 1 million, it's the same "npm install" command.
I personally like to keep third-party dependencies as minimal as possible, mostly to avoid getting 8 emails a day from dependabot telling me that a dependency of a dependency of a dependency has a regex denial of service attack and some dependency in the middle has a massive breaking change that prevents another dependency from being upgraded to include the fix. (Nevermind that I'm using it on the frontend, so if a user picks a bad regex they will slow down their own browser and nobody else's.)
It’s probably just misleading to people who don’t understand the implied semantic (which you describe above). That seems like a fair (if minor) criticism. I certainly think there’s a lot of validity in listing the manually managed dependencies, but maybe it would be clearer if we called them “manually managed dependencies” rather than simply “dependencies”?
It matters to people who are installing this software on non-internet connected machines. Granted, that's a niche these days, but there is a reason Node never took off in that space.
Do you audit the HUGE source code of the most vulnerable application you use, your web browser? It's a huge moving target with insane complexity. Didn't think so.
Do you audit the source code of the compilers used to build all the software you have installed?
> Do you audit the HUGE source code of the most vulnerable application you use, your web browser? It's a huge moving target with insane complexity. Didn't think so.
No, I do not. Relevance?
> Do you audit the source code of the compilers used to build your CPU?
No, I do not. Relevance?
> Instead of avoiding dependencies,
I never said anything about "avoiding dependencies". Are you in the wrong discussion?
> dependencies should be locked for a release cycle and audited with automated tools to instill confidence.
The parent’s grievance isn’t that projects have dependencies, but rather that projects advertise only the dependencies which Cargo doesn’t manage, which can cause confusion (the project maintainer wants to communicate that these are the only externally-managed dependencies, but at least some readers interpret this as a comprehensive list of dependencies). I’m only clarifying, not arguing in favor of the parent’s perspective.
> It's a critique of pretending that only some dependencies are dependencies.
Where exactly does this project pretend that some dependencies are not dependencies? I don't see anything like that in the blog post or the readme. In the readme I see some dependencies metioned, but it's not introduced as "here are all the dependencies", it's introduced under Requirements as "here are the commands you must run to set up your system".
If you open your distro package manager and look at the dependencies for an end-user app, it will not list header-only libraries. That's the same principle at work.
The weird thing about needing a lot of dependencies is that sysctl is a pretty simple application. It's just a list of variables you read out of the kernel. It doesn't seem like the program that manages it should be terribly complex.
Granted, this program does the manpage lookup for each variable so that adds some complexity, but that could be pre-compiled into a standardized data format pretty easily.
1. Number of dependencies alone doesn't mean much, especially that Rust's dependencies tend to be much smaller than typical C deps (Cargo's ease of use and zero overhead of static linking encourages fine-grained modularity while hassle and overhead of C shared libraries encourages big libraries). So saying there are more dependencies in Rust/Cargo is like complaining that a pizza has been cut into 12 slices instead of 4 slices, regardless of the size of the pizza.
2. Cargo makes all transitive dependencies very visible (including build-time dependencies), while other solutions don't. That doesn't mean other dependencies don't have their own dependencies: https://wiki.alopex.li/LetsBeRealAboutDependencies
A piece of software that includes source from a different project at build time, but which does not need those other projects present at run-time due to the language compiling those dependencies into target binary, does not list the build-time dependencies as part of it's run-time dependencies?
Did i get that right?
If so, I think that's ridiculous. How come you're not opening tickets on the docker or k8s or repos for the exact same behavior: there's quite a few 3rd party build dependencies that are not listed as system dependencies to install it! What about the fact that those don't list `make` or `go` package dependencies to build nor as system dependencies to use the software?
Usually this is an issue of your dependecies having dependecies having dependecies having...
It is turtles all the way down. In your cargo.toml you have like 5 dependecies, but each of those has 10 that you don't really have on the radar etc.
For really wide spread dependecies like serde I think this is okay. There are many eyeballs on it and the chances that you introduce dangerous code might be bigger if you write your own parser.
it's usually when I'm actively debugging something. And it involves flipping back and forth between journalctl and systemctl, which are both long and prone to interference in tab completion and yet similar enough to each other to cause some cognitive dissonance.
I mean, it's a really petty complaint, I'm aware. But I'm also usually already annoyed when I have to reach for it.
upstart's initctl, or even sysv/bsd-style /etc/init.d/whatever for various reasons felt less tedious. sv from daemontools is the benchmark though.
Also, instead of switching back and forth, use tmux. Open a second pane, splitting your window in half. Run journalctl in one half, and your systemctl commands in the other.
To clarify for anyone else who wants to reply to this with helpful suggestions:
I know how to use tmux. And how to use shell aliases (though I probably don't use them enough). I've been around, first used linux in 1994 kind of thing. I don't really need help, this was just a kind of petty whine.
80 comments
[ 3.4 ms ] story [ 158 ms ] threadIt looks like fans like Rust, but not many people actually want to use it, so they rewrite random stuff, so maybe others will notice it somehow and start using it.
> Figma Our real-time multiplayer syncing server (used to edit all Figma documents) is written in Rust.
> npm, Inc - Replacing C and rewriting performance-critical bottlenecks in the registry service architecture.
> OVH - We used Rust to build a high performance, highly available log management system.
> QCERT (Qatar's National CERT) - DNS log analysis pipeline entirely written in rust, running on top of our own Rust stream processing platform.
> 1Password - We use Rust to power the entire backend (encryption, networking, database, and business logic) of all our client apps.
> Fire and Emergency NZ - The New Zealand Fire Service is using a custom geolocation search engine, built in rust, that runs on embedded hardware within a fire truck to stream hazard information to a fire crew at an incident.
> Deliveroo - We are using Rust to quickly make assignment decisions in our food delivery network.
> System76 - As a Linux-based computer-manufacture, much of our infrastructure and desktop Linux projects are written in Rust. From hardware certification, flashing, and imaging; to system services and GTK3 desktop applications.
> Canonical - Everything from server monitoring to middleware!
> Cloudflare - We are using Rust as a replacement for memory-unsafe languages (particularly C) and are using it in our core edge logic.
https://www.rust-lang.org/production/users
(that "the top of one person's head" is what defines existant vs non-existant, many wouldn't agree).
I’m quite wary of jq for the reason that usually I don’t need it often enough to learn its language. That would be another piece of software like this.
*Edit based on lots of replies:* Before writing a reply that starts out with assuming that my comment says anything negative about having dependencies, or having lots of them, please take a moment to consider what I'm actually saying. This post is not a critique of dependencies, nor a critique of lots of depdendencies. It's a critique of pretending that only some dependencies are dependencies.
Sorry, but running code you didn't write yourself is a fact of life to whose risk you will have to reconcile yourself, if you want to benefit from an extraordinary patrimony of code that no one person could write in a million years.
Striving to reduce the number of dependencies is a good goal.
I don't think anyone here said it does.
Just know that you're very much not alone :)
It's not just not thinking pragmatically, it's not thinking tout court. It's a thought-terminating cliché. It's trying to reduce problem X to universal solution Y because you don't trust yourself to genuinely think it through. It's the programming equivalent of Reddit neckbeards who regurgitate (semi-accurate) names of logical fallacies from Wikipedia rather than actually evaluating the other person's argument.
I think the supply chain concerns is real and important though.
Running a naive "cargo tree" on this project tells me I'm now also trusting about 80 other projects besides this persons project. Including a Wayland client? And a "Scoped Thread Local Storage" implementation? For a sysctl replacement?
It's almost as if "a sysctl replacement?!?" is necessarily built on an extremely complex edifice of code, due to how modern computers work, which can be hidden (cf: dynamic linking) but not avoided. ;)
(Less facetiously: Yes, if you start thinking through, from first principles, all the machine code which has to run in order for this tool to function on an acceptable range of computers, you can then start to grapple with the real problem, which is unfortunately more complex than "how many Rust crates does `cargo tree` output?".)
In other words, there is a quantitative risk difference between depending on two external libraries (particularly if you pick well-vetted ones) vs. depending on 15000 libraries like some node projects.
Every additional library your build brings in, adds a small additional amount of supply chain risk.
So it's not about trying to be hardline about not depending on anything, but if you want to minimize risk you'd want to curate carefully which libraries you bring in.
Here is a recent LWN article that covers the concerns with Rust crates from an OS dev perspective: https://lwn.net/SubscriberLink/889924/321ac8bdd1fee9d9/
I'm not saying that there's necessarily anything wrong with a lot of dependencies. It can be, but that's a separate discussion. What I'm saying is that it's wrong to pretend that you don't have a lot of dependencies when you actually do.
In Rust community, it's a common knowledge that 1. If it's a high level tool, it will have multiple dependencies, and 2. The actual dependency list will be auto generated by the package managers (cargo or os) and be pinned in every release, available publicly.
If another dependency changes it's api, you immediately have a problem. Your answer may be to fix the version to a static value abd forget about it - but if a security vulnerability is found in that dependency afterward, what do you do? You probably won't even catch it.
It also sucks bigtime when you're trying to install on non-internet connected machines.
The reason that projects usually only list the non-Rust deps in their readme is because these need to be installed manually by the user in order to build or run the piece of software in question.
There would be no point in listing all direct and indirect crates that a project depends on in the readme, since that list is already in Cargo.lock anyway which is meant to also be committed.
Really don’t see any reason for this particular objection.
I understand that. It's almost spelled out in my comment. But the ones that can be automatically installed by Cargo are still dependencies.
> There would be no point in listing all direct and indirect crates that a project depends on in the readme, since that list is already in Cargo.lock anyway which is meant to also be committed.
I know. But this should at the very least be acknowledged.
> Really don’t see any reason for this particular objection.
It's entirely reasonable for someone not to want tooling to automatically grab dependencies from the internet. Such people need to know which dependencies they need to provide.
Cargo.lock specifies exactly which dependencies are required and in which version (down to git commit hashes and checksums). You can parse that file, way less error prone that doing it by hand (you can probably even fully automate the process of checking out the dependency repos).
Both crates.io and lib.rs surface this automatically right there on the crate's page.
The rust "culture" on transitive dependencies is actually laudably transparent: it's built right into the tools.
I personally like to keep third-party dependencies as minimal as possible, mostly to avoid getting 8 emails a day from dependabot telling me that a dependency of a dependency of a dependency has a regex denial of service attack and some dependency in the middle has a massive breaking change that prevents another dependency from being upgraded to include the fix. (Nevermind that I'm using it on the frontend, so if a user picks a bad regex they will slow down their own browser and nobody else's.)
Only if you accept one single, unflexible way of installing the software.
Regardless: you’re right in some regards. Cargo vendor exits, so you can ship your code dependencies alongside your own code.
Do you audit the source code of the compilers used to build all the software you have installed?
https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_Ref...
Instead of avoiding dependencies, dependencies should be locked for a release cycle and audited with automated tools to instill confidence.
No, I do not. Relevance?
> Do you audit the source code of the compilers used to build your CPU?
No, I do not. Relevance?
> Instead of avoiding dependencies,
I never said anything about "avoiding dependencies". Are you in the wrong discussion?
> dependencies should be locked for a release cycle and audited with automated tools to instill confidence.
Personal preference, open to debate.
Where exactly does this project pretend that some dependencies are not dependencies? I don't see anything like that in the blog post or the readme. In the readme I see some dependencies metioned, but it's not introduced as "here are all the dependencies", it's introduced under Requirements as "here are the commands you must run to set up your system".
If you open your distro package manager and look at the dependencies for an end-user app, it will not list header-only libraries. That's the same principle at work.
Well, it will list them in build dependencies (e.g. build-depends in Debian).
But the project doesn't do that? It lists requirements and "runtime dependencies", aka stuff that you have to set up by hand.
You're the only person asserting this is an exhaustive list of dependencies, with no evidence in support, and against all visible evidence.
2. Cargo makes all transitive dependencies very visible (including build-time dependencies), while other solutions don't. That doesn't mean other dependencies don't have their own dependencies: https://wiki.alopex.li/LetsBeRealAboutDependencies
A piece of software that includes source from a different project at build time, but which does not need those other projects present at run-time due to the language compiling those dependencies into target binary, does not list the build-time dependencies as part of it's run-time dependencies?
Did i get that right?
If so, I think that's ridiculous. How come you're not opening tickets on the docker or k8s or repos for the exact same behavior: there's quite a few 3rd party build dependencies that are not listed as system dependencies to install it! What about the fact that those don't list `make` or `go` package dependencies to build nor as system dependencies to use the software?
It is turtles all the way down. In your cargo.toml you have like 5 dependecies, but each of those has 10 that you don't really have on the radar etc.
For really wide spread dependecies like serde I think this is okay. There are many eyeballs on it and the chances that you introduce dangerous code might be bigger if you write your own parser.
alias r=sudo systemctl restart alias s=sudo systemctl status
Or something like that. It's pretty quick to define and redefine aliases on the fly.
I mean, it's a really petty complaint, I'm aware. But I'm also usually already annoyed when I have to reach for it.
upstart's initctl, or even sysv/bsd-style /etc/init.d/whatever for various reasons felt less tedious. sv from daemontools is the benchmark though.
Also, instead of switching back and forth, use tmux. Open a second pane, splitting your window in half. Run journalctl in one half, and your systemctl commands in the other.
I know how to use tmux. And how to use shell aliases (though I probably don't use them enough). I've been around, first used linux in 1994 kind of thing. I don't really need help, this was just a kind of petty whine.
>systeroid is "sysctl on steroids"