Announcing Cachix - Binary Cache as a Service

Hi all,

I’m proud to announce Cachix - Binary Cache as a Service

I’ve written a blog post about the motivation why I spent two months on this: Domen Kožar

But https://cachix.org/ should be self explainatory to someone familiar with Nix.

Feedback welcome! Domen

9 Likes

Cool!

I think I want to use this to provide a easier way for people to test the builds done by R. RyanTM. Does everyone using the cache need a Cachix account and the cachix tool installed? If not, it would be nice to see some alternate instructions for Getting Started #5.

Ryan

1 Like

Users of your cache just need to modify nix.conf accordingly, which is what “cachix use ” does without any authentication. Once it’s part of nixpkgs it should be really easy for anyone to add new binary caches.

1 Like

Thanks! I added it to nixpkgs-update. Here is an example of the instructions I currently have: quodlibet: 4.0.2 -> 4.1.0 by r-ryantm · Pull Request #41523 · NixOS/nixpkgs · GitHub

I ran into a couple of problems while setting it up:

  1. The installation command failed to use the substituter so it had to build it from scratch:
    nix-env -if https://github.com/cachix/cachix/tarball/master --substituters https://cachix.cachix.org --trusted-public-keys cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM=
    warning: ignoring untrusted substituter 'https://cachix.cachix.org'
    
  2. My user is not a trusted-user so cachix use fails
    $ cachix use r-ryantm
    warn: $USER is not in trusted-users, requiring sudo.
    
    MustBeRoot "Run command as 'sudo' or upgrade to Nix 2.0.1 or newer."
    

Here is my nix-info output:

$ nix-info
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs' does not exist, ignoring
error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I), at (string):1:9
system: 0, multi-user?: no, version: nix-env (Nix) 2.0.2, channels(root): "", channels(ryantm): "", warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs' does not exist, ignoring
error: file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I), at (string):1:1
nixpkgs: 0

I was able to work around these problems by running it all with sudo, but that is less than ideal. Probably I’m missing some configurations that will fix this.

Ryan

1 Like

Adding my user nix.trustedUsers (https://github.com/NixOS/nixpkgs/blob/fc1b5ecc9248cc133b590565ad1bf2fdbac60ed2/nixos/modules/services/misc/nix-daemon.nix#L312) fixed both of these issues!

Ryan

1 Like

Thanks for the report @ryantm, workaround is indeed Installing cachix builds everything from source if Nix user isn't trusted · Issue #26 · cachix/cachix · GitHub

I’ll add some docs to the getting started instructions.

1 Like

Wow, this is really neat, I have a decent chunk of out-of-tree opam library derivations required for bulding & testing opam2nix (GitHub - timbertson/opam2nix-packages: nix expressions for the official opam repository, using opam2nix) which this sounds perfect for.

I’m a little worried about the trust model though, and perhaps you could clear this up if I’m wrong about how any this works. Nix is built to be reproducible, but as far as I know it can’t actually be enforced (aside from fixed-output derivations, which can be verified). The trust we place in cache.nixos.org is based on trusting the operators to have a vanilla hydra running, publishing derivations that were really built from the corresponding nix expressions.

If a derivation produces /nix/store/abcd1234-foo, what’s to stop a malicious user from overwriting that directory manually on their own system, populating it with malicious data, and then giving that to cachix push? If I cachix use some-repo, is it possible that repo might provide poisoned implementations of any derivation nix-wide?

If I cachix use some-repo, is it possible that repo might provide poisoned implementations of any derivation nix-wide?

tl;dr: Yes.

Long answer: yes, by cachix useing somebody’s cache, you are placing your full trust in:

  • cachix.org (Domen): since this is where the cache key is fetched from (see for example the JSON at https://cachix.cachix.org/). You could manually verify the key against other sources though.
  • The owner of the cache key, as they can sign whatever narinfos they want.

I say “full trust” because as you mentioned, there’s nothing stopping the cache from containing store paths that you may find as part of your system — a malicious cache owner could for example serve up a malicious /nix/store/xxyyzz-nix-2.0.4, and (since that’s where nix-daemon comes from) get root privileges on your machine when you update to that particular version of nix. There are however two potential mitigating factors I can think of:

  • for nix 2.0.1 and later, cachix will write the settings to your user nix.conf (~/.config/nix/nix.conf) rather than the system-wide one, so nix commands run as root will not use the binary cache;
  • (caveat: I’m not sure about nix’s behaviour for multiple binary caches so this may not apply) if nix uses binary caches strictly in the order in which they’re listed, then paths such as nix which can be found on cache.nixos.org will not be fetched from the cachix cache.

As an aside, the way your proposed for an attacker to push their malicious code to their cache won’t work, since nix verifies the integrity of paths (i.e. “are the contents of the path the same as when it was registered to the store”) before pushing them. Of course, there are other ways of achieving this — meddling with the build itself by replacing files in the build directory for instance.

Thanks for that, @lheckemann. I assume the intensional store model (Intensional store model · Issue #296 · NixOS/nix · GitHub) would remove the need for trust in both the cache owner and Domen? As it is I’d still like to use cachix, but will have to keep it to stores from users I already trust.

Not really. Someone still has to perform the actual build and attest that derivation X produces output Y — the intensional store model would just mean that differing Ys live in different store paths.

1 Like

For some reason I didn’t see notifications for these questions :slight_smile:

@lheckemann is right about the trust model, I’d like to add how I want to address this in the future:

a) keys can be mirrored and since I don’t expect caches to be added very often, there could be an independent source to verify that (configurable via cachix config). The good news is, you only configure the key at the beginning when setting up the cache so it’s harder to do attacks (even if someone compromises cachix).

b) I’ve left some thoughts on Idea for cachix.org: Publicly stated trust and trust-as-a-service · Issue #101 · cachix/cachix · GitHub

Domen