Git Product home page Git Product logo

nar-serve's Introduction

nar-serve - Serve NAR file content directly from cache

Push your build artifacts to one place.

All the files in https://cache.nixos.org are packed in NAR files which makes them not directly accessible. This service allows to download, decompress, unpack and serve any file in the cache on the fly.

Use cases

  • Avoid publishing build artifacts to both the binary cache and another service.
  • Allows to share build results easily.
  • Inspect the content of a NAR file.

Development

Inside the provided nix shell run:

./start-dev

This will create a small local server with live reload that emulates now.sh.

Currently, the default port is 8383. You can change it by setting the PORT environment variable.

Usage

Store contents can be fetched via a simple HTTP GET request.

Append any store path to the hostname to fetch and unpack it on the fly. That's it.

E.g.:

NAR archives also contain information about the executable bit for each contained file. nar-serve uses a custom HTTP header named NAR-executable to indicate whether the fetched file would be executable.

Configuration

You can use the following environment variables to configure nar-serve:

Name Default value Description
PORT 8383 Port number on which nar-service listens
NAR_CACHE_URL https://cache.nixos.org The URL of the Nix store from which NARs are fetched

Contributing

Contributions are welcome!

Before adding any new feature it might be best to first discuss them by creating a new issue in https://github.com/numtide/nar-serve/issues .

All code is licensed under the Apache 2.0 license.

nar-serve's People

Contributors

chkno avatar dependabot[bot] avatar flokli avatar kiaragrouwstra avatar mic92 avatar rizary avatar stv0g avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nar-serve's Issues

Add local LRU disk cache

Instead of downloading the NAR files over and over from the cache, it might be nice to keep a local copy. The LRU cache should be based on a size or percent of the disk space available.

Add S3 backend

Some people's binary cache live in S3.

This will require to extend the go-nix library so that it can parse a store URI and return the right backend for us.

Suggestion: Make use of more HTTP caching headers

Hello,

It seems like HTTP caching headers could score you some very cheap, significant wins.

I saw Cache-Control already returns immutable, I think you could probably push that to public, max-age=31536000, immutable, as well as providing ETag, Last-Modified and Expires.

There are more cases where those can be returned as well, I think that any response for which a NAR was successfully fetched, so directory listing, redirects, but also 404s when a file was not found.

MDN has a great resource about this: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching

Pretty cool project!

Bests

Expose the executable bit into a HTTP header

The NAR archive doesn't store any file attributes except the file type, and whenever the file is an executable.

It would be nice to expose whenever a file is executable in a HTTP header.

Eg:

X-Nar-Executable: true

?

Implement request merging

When multiple clients access the same NAR file at the same time, we could download the file from the S3 bucket only once.

  1. Add a concurrent lock on a per-derivation hash basis.
  2. Associate the NAR stream to the lock.
type CachedBinaryCacheReader struct {
  Reader BinaryCacheReader
  Lock map[string]io.ReaderCloser
  Mutex sync.Mutex
}

func (r CachedBinaryCacheReader) GetFile(ctx context.Context, path string) (io.ReadCloser, error) {

}

Volume plugin for container orchestrators?

Is your feature request related to a problem? Please describe.

My situation is that I build a system that totals around 5-10GB (currently with debs, but transitioning to Nix) and then run an extensive simulation-based testing framework on that system. Regardless of what I do about build (eg, moving to Hydra), I'd like to be able to continue using Jenkins and Kubernetes workers for the testing aspect of it.

Some "conventional" options could be:

  • Just install all the Nix outputs that my tests need on demand.
  • Pre-cook an image with all my base stuff in it (potentially at the beginning of each day), and use that as the starting point for the on-demand test installation.

Both of these options potentially incur a lot of unnecessary transfer and archive manipulation and don't really leverage the power of Nix.

Describe the solution you'd like

This may be well out of scope for this project, but it would be super cool if it was able to act as a Kubernetes volume plugin and transparently fill requests for /nix/store paths from a cache that was shared between all containers on the host:

https://github.com/kubernetes/community/blob/master/sig-storage/volume-plugin-faq.md

This could be set up as an overlay so that writes would always be container-local, but reads would fall through to the volume.

Describe alternatives you've considered

See above.

Support multiple stores

It would be nice if we can define multiple store URLs which will be tried one after another, or in parallel.

My use case here: Query my personal binary cache and fall back to cache.nixos.org afterwards.

Use the .ls files to improve performance

Nix clients who upload with write-nar-listing = true also upload a .ls file that contains all the archive metadata.

nix run nixpkgs.{brotli,curl, bash} -c \
curl -v https://cache.nixos.org/$(readlink $(which bash) | cut -d/ -f4 | cut -d- -f1).ls | brotli -d

This could be used to quickly determine whenever a file exists and also create directory listings.

Support binary caches with a different storeDir

The API currently only works if the storeDir is set to the default /nix/store. It would be nice if other stores were supported.

I think this would require to change the API shape a bit.

Instead of /nix/store/<hash>..., load the storeDir and add a prefix: /unpack/<storeDir>/<hash>...

Regression in 0.6.0: Can't fetch files inside archives: Leading slash

From #20, the new 0.6.1's api/unpack/index.go, it looks like hdr.Path has /-prefixed names like /bin/hello, whereas the old 0.4.0's api/unpack/index.go, hdr.Name names are not /-prefixed, like bin/hello.

This breaks fetching single files from inside archives (server-side unpacking).

To Reproduce

Steps to reproduce the behavior:

  1. Fix the missing import os in nixos/tests/nar-serve.nix
  2. Run nix-build nixos/tests/nar-serve.nix

Expected behavior

Test passes

Actual behavior

Test fails: request returns 404 not found:

server: must succeed: curl -o hello -f http://localhost:8383/nix/store/cv79b81pjmva78whwwpr66l5mfj4pijh/bin/hello
server # [   29.716220] nar-serve[776]: 3 [cv79b81pjmva78whwwpr66l5mfj4pijh bin hello]
server # [   29.722451] nar-serve[776]: Fetching the narinfo: cv79b81pjmva78whwwpr66l5mfj4pijh.narinfo from: http://localhost/
server # [   29.732232] nar-serve[776]: narinfo StorePath: /nix/store/cv79b81pjmva78whwwpr66l5mfj4pijh-hello-2.12
server # [   29.736556] nar-serve[776]: URL: nar/14dp7chhq8akhgyqvyfkdwgg4d696agd0zga80ib0f382qhc6p8c.nar.xz
server # [   29.741487] nar-serve[776]: Compression: xz
server # [   29.743802] nar-serve[776]: FileHash: sha256:14dp7chhq8akhgyqvyfkdwgg4d696agd0zga80ib0f382qhc6p8c
server # [   29.748350] nar-serve[776]: FileSize: 43624
server # [   29.751017] nar-serve[776]: NarHash: sha256:0wbkw4v6ykfmm0jjp61z28f9nsf8wzx2cb4mz4g0gnv64sj2vsdk
server # [   29.754678] nar-serve[776]: NarSize: 181368
server # [   29.755824] nar-serve[776]: References: cv79b81pjmva78whwwpr66l5mfj4pijh-hello-2.12 f3qlm2873bxlhxns4lrmrinvbzn933pj-glibc-2.34-210
server # [   29.759341] nar-serve[776]: fetching the NAR: nar/14dp7chhq8akhgyqvyfkdwgg4d696agd0zga80ib0f382qhc6p8c.nar.xz
server # [   29.771493] nar-serve[776]: newPath bin/hello
server # [   29.778593] nar-serve[776]: [negroni] 2023-05-26T00:40:05Z | 404 |   63.002979ms | localhost:8383 | GET /nix/store/cv79b81pjmva78whwwpr66l5mfj4pijh/bin/hello
server # curl: (22) The requested URL returned error: 404
...
Exception: command `curl -o hello -f http://localhost:8383/nix/store/cv79b81pjmva78whwwpr66l5mfj4pijh/bin/hello` failed (exit code 22)

System information

NixOS 23.05beta78.04aaf851167

Additional context

Discovered in NixOS/nixpkgs#178851 (comment)

Looks easily fixed: #24

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.