Multi-tenant Nix Binary Cache

Related tags

Cryptography attic
Overview

Attic

Attic is a self-hostable Nix Binary Cache server backed by an S3-compatible storage provider. It has support for global deduplication and garbage collection.

Attic is an early prototype.

⚙️ Pushing 5 paths to "demo" on "local" (566 already cached, 2001 in upstream)...
✅ gnvi1x7r8kl3clzx0d266wi82fgyzidv-steam-run-fhs (29.69 MiB/s)
✅ rw7bx7ak2p02ljm3z4hhpkjlr8rzg6xz-steam-fhs (30.56 MiB/s)
✅ y92f9y7qhkpcvrqhzvf6k40j6iaxddq8-0p36ammvgyr55q9w75845kw4fw1c65ln-source (19.96 MiB/s)
🕒 vscode-1.74.2        ███████████████████████████████████████  345.66 MiB (41.32 MiB/s)
🕓 zoom-5.12.9.367      ███████████████████████████              329.36 MiB (39.47 MiB/s)

Try it out (15 minutes)

Let's spin up Attic in just 15 minutes. And yes, it works on macOS too!

Goals

  • Multi-Tenancy: Create a private cache for yourself, and one for friends and co-workers. Tenants are mutually untrusting and cannot pollute the views of other caches.
  • Global Deduplication: Individual caches (tenants) are simply restricted views of the content-addressed NAR Store and Chunk Store. When paths are uploaded, a mapping is created to grant the local cache access to the global NAR.
  • Managed Signing: Signing is done on-the-fly by the server when store paths are fetched. The user pushing store paths does not have access to the signing key.
  • Scalabilty: Attic can be easily replicated. It's designed to be deployed to serverless platforms like fly.io but also works nicely in a single-machine setup.
  • Garbage Collection: Unused store paths can be garbage-collected in an LRU manner.

Licensing

Attic is available under the Apache License, Version 2.0. See LICENSE for details.

By contributing to the project, you agree to license your work under the aforementioned license.

Comments
  • nix module: error: unsupported argument 'submodules' to 'fetchGit', at /nix/store/9i8226p09g7cvih4lf24rysyx1qkxka8-source/lib/downloadCargoPackageFromGit.nix:18:5

    nix module: error: unsupported argument 'submodules' to 'fetchGit', at /nix/store/9i8226p09g7cvih4lf24rysyx1qkxka8-source/lib/downloadCargoPackageFromGit.nix:18:5

    I'm using:

    {
      imports = [
        "${(import ./nix/sources.nix).attic}/nixos/atticd.nix"
      ];
    
      services.atticd = {
        enable = true;
        credentialsFile = config.sops.secrets.attic.path;
        settings = {
          database = {
            url = "postgresql://[email protected]/attic";
          };
    
          storage = {
            type = "local";
            path = "/mnt/attic/storage";
          };
    
          # useFlakeCompatOverlay = false;
        };
      };
    }
    
    [bbigras2@nixos:/etc/nixos]$ sudo nixos-rebuild build
    building Nix...
    building the system configuration...
    error: unsupported argument 'submodules' to 'fetchGit', at /nix/store/9i8226p09g7cvih4lf24rysyx1qkxka8-source/lib/downloadCargoPackageFromGit.nix:18:5
    (use '--show-trace' to show detailed location information)
    

    nix-info (I'm still on nixos-21.11 but going to update soon):

    • system: "x86_64-linux"
    • host os: Linux 5.10.126, NixOS, 21.11 (Porcupine)
    • multi-user?: yes
    • sandbox: yes
    • version: nix-env (Nix) 2.3.16
    • channels(root): "nixos-21.11.337975.eabc3821918"
    • channels(bbigras): "home-manager-20.09"
    • nixpkgs: /nix/var/nix/profiles/per-user/root/channels/nixos
    opened by bbigras 6
  • Nix version 2.13 incompatibility:

    Nix version 2.13 incompatibility: "The program must call nix::initNix() before calling any libstore library functions. on attic push"

    I am getting the error

    The program must call nix::initNix() before calling any libstore library functions.
     (core dumped) attic push remote $WORKSPACE/$val
    

    (where $WORKSPACE/$val is a symlink to a store path which has worked just fine).

    I am on revision c77b5fb64ee0d02299eee3268da2ce56b6575f6c If there is anything to help you debug it, let me know.

    The output of attic cache info:

    /nix/store/m7fmj73cz1zhyahwhw6s8qs8l1gqllji-attic-0.1.0/bin/attic cache info remote
    Public: false
               Public Key: remote:xxx
    Binary Cache Endpoint: https://my-server.com/remote
             API Endpoint: https://my-server.com
          Store Directory: /nix/store
                 Priority: 41
      Upstream Cache Keys: ["cache.nixos.org-1"]
         Retention Period: Global Default
    
    opened by gador 5
  • Support for asynchronous uploading

    Support for asynchronous uploading

    I think it would be quite helpful if the attic client supported asynchronous uploading when using it via the nix post-build-hook.

    Maybe the client could write the paths of the binaries to a file and another instance of the client (via systemd) could be watching said file and upload all binaries that appear.

    Is this something you’d accept a PR for?

    opened by chris-02 2
  • use system certificate store for attic client

    use system certificate store for attic client

    I just ran into an issue using attic with a self hosted CA: the attic client does not use the certificate store of the system. I don't know if this is an intentional design decision. If it isn't this PR should fix the issue.

    opened by chris-02 0
  • error: anonymous function at /nix/store/5l147bk6zqi6kgbs3b9gxma1g4yx2gbk-nixos-22.11.1530.09b46f2c1d8/nixos/pkgs/build-support/rust/import-cargo-lock.nix:3:1 called with unexpected argument 'allowBuiltinFetchGit'

    error: anonymous function at /nix/store/5l147bk6zqi6kgbs3b9gxma1g4yx2gbk-nixos-22.11.1530.09b46f2c1d8/nixos/pkgs/build-support/rust/import-cargo-lock.nix:3:1 called with unexpected argument 'allowBuiltinFetchGit'

    with 70ae61b59114982a2685f67b35405f7ca0bf5b6f I got this, when using pkgs.callPackage attic { inherit rustPlatform; };:

    EDIT: using package.nix.

    error: anonymous function at /nix/store/5l147bk6zqi6kgbs3b9gxma1g4yx2gbk-nixos-22.11.1530.09b46f2c1d8/nixos/pkgs/build-support/rust/import-cargo-lock.nix:3:1 called with unexpected argument 'allowBuiltinFetchGit'
    
           at /nix/store/5l147bk6zqi6kgbs3b9gxma1g4yx2gbk-nixos-22.11.1530.09b46f2c1d8/nixos/pkgs/build-support/rust/build-rust-package/default.nix:64:36:
    
               63|     if cargoVendorDir != null then null
               64|     else if cargoLock != null then importCargoLock cargoLock
                 |                                    ^
               65|     else fetchCargoTarball ({
    (use '--show-trace' to show detailed location information)
    

    Originally posted by @bbigras in https://github.com/zhaofengli/attic/issues/12#issuecomment-1383285319

    opened by bbigras 3
  • Short-term key exchange to allow provenance and revocation?

    Short-term key exchange to allow provenance and revocation?

    Please note: This isn't really a request for a feature to be implemented, it is just to get ideas and a discussion going. I don't know if people consider this part of their threat model, but it's something I mulled over, and I'm interested in hearing the ideas of other people who have written binary cache software. Attic looks great in any case!

    I quite like Attic at a glance. I have developed several Nix binary caches in the past, including Eris, and an an unreleased "serverless" one running on WASM/JS function services, which I also planned to have many of the same features as Attic. But I'd like to mention something since I mulled over it a bit.

    My serverless solution also has server-side signing, since it is relatively easy to compute the signature for a .narinfo, and makes many bugs like nixos/nix#6960 irrelevant. It's nice. But I think it's important to note that server-side signing acts as a kind of oracle; anything uploaded to the binary cache is implicitly signed as if it was authored by you. This means that if anyone uploads anything invalid or garbage (or backdoored, e.g. a CI system) it can and will be shown as "authentic." There is also no secure provenance or identity attached to the original upload; it is not possible to prove after the fact that where it came from.

    For instance, if someone steals an authentication key from a (valid) person doing uploads, they can then upload anything they want with abandon and it can never be tied back to them. For example, given the way I think the upload works from the description in #7, they can do things like populate "correct" hashes with trojaned binaries e.g. deadbeef-firefox-100 is a valid hash the user computes, but they upload a trojaned binary under this hash. Now, if someone else tries to upload deadbeef-firefox-100, the deadbeef.narinfo file gets located, and therefore the nar itself is silently discarded. The cache then remains infected for all time until it is purged.

    This is sort of a different take on the original problems signatures solved; current non-content-addressed store derivations take their hash from their inputs, not their output; keys are used to authenticate that the output binary is authentically coming from a trusted source, because a malicious source could compute the same input hash, but give you a trojaned binary under it. What you want is a kind of non-repudiation so that when you get an upload, it cannot be denied where it came from. CA derivations partially address this because they're self authenticating, so when you look up a hash, it can be verified that it is legitimate immediately. But you still don't know who gave it to you.

    One way around this is to sign uploads in a lock-step way. First, an agent requests to do an upload, and establishes some identity that can be validated e.g. "I am github CI runner on commit hash 0xDEADBEEF running at 12pm UTC, with the given $GITHUB_TOKEN", and you check the $GITHUB_TOKEN is legitimate on the server via OAuth. You then issue a new short-term ed25519 signing key in return, which can be used to sign uploads for a short time frame, say, 15 minutes. The agent then uploads all its derivations under this signing key, within this time frame, and this is validated by the server. The key is then marked as "permissible, but not usable for any further signatures" after the 15 minutes. Then, when a narinfo is requested, it is identifiable where it came from at what time through the signature. This signature can then be replaced by a new signature "on the fly", and this replaced signature is what is shown to the user, just like it works today. This design is similar to the way SLSA Level 3 guidelines operate, as they require cryptographically sure proof of provenance. This approach isolates the user-facing key from the key used to authenticate the builder itself, rather than relying purely on simple bearer token schemes (which I suspect is what is used now, though I admit I haven't read the code thoroughly yet...)

    Another very good thing to note is that this allows real revocation; assuming it is ever discovered that a build is compromised for some reason, it's now possible to track this down to individual keys assigned during the build step, and revoke those keys behind the scenes e.g. when a narinfo is requested that is associated with a revoked key, simply 404 instead.

    In the world of CA derivations, this provenance is still useful for those reasons, though the need for end-user signatures is not needed since the hashes allow self authentication.

    Anyway, I'd be interested to know your thoughts on something like this. It is complex to work out the details, but I think a significant step up over the current state of the art in cache security and helps operate closer to modern standards like SLSA. With a globally deduplicated cache it's also important since any user can easily "poison the well" for all other users, so having some auditability for cases like this is nice, which is something I realized while thinking about multi-tenancy and deduplication myself.

    opened by thoughtpolice 1
  • Native Nix store implementation / standardized REST API

    Native Nix store implementation / standardized REST API

    Both cachix and attic implement their own push-related endpoints, that are, for good reason, incompatible with Nix's own HTTP binary cache store. This is not so great for interoperability.

    What does the attic API look like? Is it compatible with the cachix API? Would you be interested in working towards a native HttpBinaryCacheStore subclass in Nix?

    Some benefits of a store implementation:

    • No need to install an extra package in the CIs like GitHub Actions
    • Automatic support in deployment tools that use nix copy
    • Support for queries like nix path-info --store
    opened by roberth 2
Tooling for the simple-package-paths Nix RFC

Implementation Index the tree for references. If .git exists, use ls-tree equivalent Check the validity of the pkgs/unit directory Should only contain

Nixpkgs Architecture Team 3 Jan 18, 2023
Generate Nix fetcher calls from repository URLs [maintainer=@figsoda]

nurl Generate Nix fetcher calls from repository URLs $ nurl https://github.com/nix-community/patsh v0.2.0 2>/dev/null fetchFromGitHub { owner = "nix

Nix community projects 103 Jan 29, 2023
A type-safe Rust interface to the Nix CLI

runix A typesafe interface to the nix CLI. by flox Installation Install with cargo add (Rust >= 1.64) cargo add runix Alternatively, manually add runi

flox 43 Mar 6, 2023
Snapshot testing tool for Nix based on haumea [maintainer=@figsoda]

namaka Snapshot testing tool for Nix based on haumea nix shell github:nix-community/namaka namaka check # run checks namaka review # review pending sn

Nix community projects 30 Apr 17, 2023
A fast and secure multi protocol honeypot.

Medusa A fast and secure multi protocol honeypot that can mimic realistic devices running ssh, telnet, http, https or any other tcp and udp servers. W

Simone Margaritelli 268 Dec 26, 2022
multi-market crank for serum-dex

A performance and cost optimized serum-dex crank that allows combining multiple market cranking instructions into a single transaction, while concurrently generating the crank instructions allowing for increased throughput.

SolFarm 33 Nov 23, 2022
An encrypted multi client messaging system written in pure Rust

?? Preamble This is a pure Rust multi-client encrypted messaging system, also known as Edode's Secured Messaging System. It is an end-to-end(s) commun

Edode 3 Sep 16, 2022
Eternally liquid. Forward compatible. Nested, conditional, & Multi-resourced NFTs.

RMRK Substrate Rust Setup First, complete the basic Rust setup instructions. Run Use Rust's native cargo command to build and launch the template node

RMRK Team 67 Dec 25, 2022
Multi Party Key Management System (KMS) for Secp256k1 Elliptic curve based digital signatures.

Key Management System (KMS) for curve Secp256k1 Multi Party Key Management System (KMS) for Secp256k1 Elliptic curve based digital signatures. Introdu

[ZenGo X] 61 Dec 28, 2022
Rust implementation of multi-party Schnorr signatures over elliptic curves.

Multi Party Schnorr Signatures This library contains several Rust implementations of multi-signature Schnorr schemes. Generally speaking, these scheme

[ZenGo X] 148 Dec 15, 2022
A standalone Aleo prover build upon snarkOS and snarkVM, with multi-threading optimization

Aleo Light Prover Introduction A standalone Aleo prover build upon snarkOS and snarkVM, with multi-threading optimization. It's called "light" because

Haruka Ma 91 Dec 29, 2022
Two-party and multi-party ECDSA protocols based on class group with Rust

CG-MPC-ECDSA This project aims to implement two-party and multi-party ECDSA protocols based on class group with Rust. It currently includes schemes de

LatticeX Foundation 16 Mar 17, 2022
Cryptle: a secure multi-party Wordle clone with Enarx

Cryptle: a secure multi-party Wordle clone with Enarx Wordle is a popular web-based game, where a single player has to guess a five-letter word in six

Nick Vidal 2 May 9, 2022
User-friendly secure computation engine based on secure multi-party computation

CipherCore If you have any questions, or, more generally, would like to discuss CipherCore, please join the Slack community. See a vastly extended ver

CipherMode Labs 356 Jan 5, 2023
Ethereum JSON-RPC multi-transport client. Rust implementation of web3 library

Ethereum JSON-RPC multi-transport client. Rust implementation of web3 library. ENS address: rust-web3.eth

Tomasz Drwięga 1.2k Jan 8, 2023
A basic contract to facilitate multi-hop FIN swaps

Fin Multi A basic contract designed to support consolidation of staking "dust" into a single asset, via FIN Market Swaps. ExecuteMsg requires a Vec<Ve

Kujira 2 Oct 11, 2022
CosmWasm multi-contract testing framework

Multi Test: Test helpers for multi-contract interactions Warning: Alpha Software Designed for internal use only. This is used for testing cw-plus cont

CosmWasm 7 Dec 6, 2022
Freelance payment protocol written in Rust.. (with multi-sig signing for dispute settling)

Freelance Escrow payment protocol ?? About The freelance protocol is a protocol built on decentralized and open systems such as blockchain and decentr

Femi Bolaji 4 Jan 3, 2023
A Multi-chain Decentralized Exchange (DEX) built on CosmWasm for the WYND DAO.

WynDex A Multi-chain Decentralized Exchange (DEX) built on CosmWasm for the WYND DAO. Overview License The initial pool types were copied from astropo

null 7 Jan 31, 2023