-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
editorial: update mapping of Nix terminology to the SLSA Package model #987
editorial: update mapping of Nix terminology to the SLSA Package model #987
Conversation
✅ Deploy Preview for slsa ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the help! I know almost nothing about Nix, and this has taught me a lot. I have a few questions.
/cc @mlieberman85 who added the original definitions
docs/spec/v1.1/terminology.md
Outdated
<td><a href="https://nixos.org/manual/nix/stable/glossary.html#gloss-store-object">Store Object</a>? | ||
<td>Package or <a href="https://nixos.org/manual/nix/stable/glossary.html#gloss-derivation">Derivation</a> | ||
<td><a href="https://nixos.org/guides/how-nix-works.html">Nix</a> (e.g. <a href="https://nixos.org/">NixOS</a>) | ||
<td><a href="https://github.com/NixOS/nixpkgs">Nixpkgs</a> / <a href="https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake">Flakes</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the documentation, I think the following might be a closer fit for Nixpkgs?
- Package ecosystem = Nixpkgs (NixOS)
- Package registry = "Repository"? Is there a name for the general concept, i.e. if you point to something other than https://github.com/NixOS/nixpkgs?
- Package name = Package name (
pname
) or attribute name - Package artifact = ? - see other comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Nix ecosystem is challenging to describe, please bear with me, I will do my best to describe it.
Nix is the package manager. Nixpkgs is the largest community managed repository of packages. And there are other user managed repositories (e.g. NUR or just individual git repositories). Nixpkgs is a set of freeform Nix expressions (no schema), as is every other Nix (user managed) package repository before Flakes. This made it difficult to consume packages without first looking at the Nix expression to know what attributes to access. Nix Flakes have a schema, standard mechanism for pinning, evaluation caching, and provide for hermetic evaluation. But packages are still defined using Nix expression language (flake or no flake), and evaluated by Nix package manager command line tool.
I am not sure that is all totally clear. But just to say that Nix is one ecosystem, and flakes are just an additional layer.
For example, Nixpkgs is also a Nix Flake. So you can access packages via the Flake schema, or via convention existed before Nix Flakes (i.e. via default.nix file in root of repo, and nested attribute paths).
In looking at how the other ecosystems are documented on the SLSA terminology page, the package ecosystem appears to be the name of the package manager; in this case, Nix is the package manager. Nix is currently supported on any Linux distro and on macOS (so, more than NixOS).
For the Package Registry column, I would say the general term would be "Repository" (in fact Nix Flakes are strongly tied to git repository - i.e. nix will ignore "dirty" files during evaluation; files must be staged or committed; this is part to the pure evaluation, e.g. hermitic build). Since Nixpkgs is the community repository, I guess it would be the one listed here.
For the Package name, this would be an attribute path determined by convention when not using flakes, and would be an attribute under the "packages" attribute of the flake schema when using flakes, i.e. a flake ref (there is no attribute path under "packages", as flakes do not allow nesting attributes below the schema defined attributes). When you build a package using the traditional Nixpkgs, you can specify the pname (of derivation) or the "package attribute name" (attrset path). So, I think we could say "Package Name" as you have indicated when using traditional nix, or flake ref when using flakes interface.
For Package artifact, when you build a Nix package, there are two underlying steps that occur, instantiation and realization. The instantiation step takes the Nix expression for a derivation (this is defined using the builtin derivation function), evaluates the expression, and creates a store derivation. The store derivation is the "build recipe". These are the .drv files in the nix store (/nix/store). The realization step takes the store derivation, and builds the package, producing a store path (the output of the build). This will be in the nix store with a name consisting of the derivation pname and an input-address (calculated from the derivation inputs). Store paths are usually symlinked to user's directory, or added to user's environment via PATH.
n.b.
Nix package manager can be used on any Linux or macOS. NixOS is a linux distro that is built using the Nix package manager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My hope would be to not make Nix package manager look like a splintered ecosystem. It is just a little confusing with two interfaces (the traditional interface and the flake interface). Both interfaces use derivations and produce store paths.
I hope this is helping 🤯
docs/spec/v1.1/terminology.md
Outdated
<td><a href="https://nixos.org/manual/nix/stable/glossary.html#gloss-store-object">Store Object</a>? | ||
<td>Package or <a href="https://nixos.org/manual/nix/stable/glossary.html#gloss-derivation">Derivation</a> | ||
<td><a href="https://nixos.org/guides/how-nix-works.html">Nix</a> (e.g. <a href="https://nixos.org/">NixOS</a>) | ||
<td><a href="https://github.com/NixOS/nixpkgs">Nixpkgs</a> / <a href="https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake">Flakes</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the documentation, it looks like the following might be a closer fit for Flakes:
- Package ecosystem = Nix Flakes (NixOS)
- Package registry = Registry (or maybe "global registry") = the thing that maps identifiers to locations
- Package name = Flake reference (flakeref)
- Package artifact = Flake (but see other comment)
What do you think? The output attribute seems like a sub-artifact, while store path is an identifier not an artifact itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flakes can have more than packages. They can output modules, configurations, shells, etc.
A flake can have many packages. Nixpkgs is an example. There is no central authority for finding all flakes (or nix repositories in general).
So, it may still be best to refer to Nixpkgs as the main community repository, when referring to traditional nix or nix flakes (since it is both).
I think Package name should be Flake ref as you have specified when using flakes.
Package artifact would still be a store path. Nix is still evaluating a nix expression that produces a store derivation, that is then realized to a store path.
docs/spec/v1.1/terminology.md
Outdated
<td><a href="https://nixos.org/guides/how-nix-works.html">Nix</a> (e.g. <a href="https://nixos.org/">NixOS</a>) | ||
<td><a href="https://github.com/NixOS/nixpkgs">Nixpkgs</a> / <a href="https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake">Flakes</a> | ||
<td><a href="https://github.com/NixOS/nixpkgs">Nixpkgs</a> attribute path / <a href="https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake">Flake</a> output attribute | ||
<td><a href="https://nixos.org/manual/nix/stable/glossary.html#gloss-store-path">Store Path</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused by Nix here. What is the actual artifact (sequence of bytes) distributed as part of Nix? I don't think it's the "Store Path". The old version said "Derivation" which sounded right to me? In other words, when you "fetch" something from Nixpkgs, you actually fetch the derivation?
For Flakes, I think the thing being distributed is called a "flake". Is that right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say the actual artifact is the store path resulting from the instantiation and realization of the nix derivation. Derivation is slightly overloaded - there is the derivation expression, which is written using the builtin derivation function, and there is the store derivation, which is the evaluated derivation expression written to the nix store (this is just the "build recipe"). The final output of a package build is not the derivation, it is the artifact(s) of the build.
For Flakes, the flake is just a repository with a flake.nix file. So, just a well-defined entry point for Nix. In the end, the output attribute set of the flake schema is still a set of name/value pairs with the values being nix expressions that must conform to the types in the schema (e.g. packages must be derivation expressions).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I should mention Nix is a "from source" package manager. It also support binary substitution via a binary cache. Because store paths are input addressable, as long as the inputs of the derivation have not changed, a binary substitute can be used. This is based on the assumption that building again would result in the same binary (not exactly the case unless the build is truly reproducible). So when a user "fetches" a "package" using Nix package manager and the Nixpkgs package repository, they are usually getting the binary substitute from the Nix binary cache (this is populated by a continuous integration service called Hydra), which is placed in their local nix store, and usually symlinked or added to PATH. And the binary cache is basically a remote nix store (and the binary substitute is the store path in the cache).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this is all we need. It would avoid getting into the interface details of the package manager (traditional vs flake). It is accurate regardless of traditional interface or flake interface.
- Package ecosystem = Nix (NixOS)
- Package registry = Nixpkgs
- Package name = Derivation name
- Package artifact = Derivation output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. This is all amazingly helpful!
For this model, we are exclusively interested in the things that cross the trust boundary between client and registry. Here's a simple data flow diagram that might help (we should probably add this to the site):
A package ecosystem is a convention for mapping names to artifacts. A registry is one authority for this mapping. A client queries a registry with a name and gets back an artifact. For example, in NPM, the client requests a name plus some additional qualifiers (e.g. name react
version 18.2.0
) and they get back a tarball.
I'm still having a hard time wrapping my head around Nix. Let me take a shot at explaining and see if this is anywhere close. When a user runs something like nix install <name>
, the Nix client does the following:
- If there is a local pre-built version of
<name>
already on the machine (in the Nix store?), use that. - Else if there is a local derivation (?) for
<name>
, build and use that. - Else query an external binary cache for
<name>
. If one is found, download and use that. - Else query an external registry (repository?) such as Nixpkgs for a derivation of
<name>
. If one is found, download, build, and use that. - Else fail.
Does that sound even somewhat correct? If so, it is the things downloaded on steps 3 and 4 that we care about, because those are the ones that cross the trust boundary of local client to remote package registry. SLSA is concerned about tampering in the registry or by a package owner: does the artifact that we got really correspond to what <name>
ought to be?
Assuming that's all right, what are the things that are actually downloaded in steps 3 and 4? "Binary substitute" and "derivation", respectively?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I would say that is correct.
I just do not think of the nix derivation expression as a distributed artifact. The nix derivation expression is like a homebrew formula, a pacman PKGBUILD, etc. E.g. the formula or PKGBUILD are not listed as package artifacts for their respective package ecosystem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still thinking through this with you...
Package artifact - A file or other immutable object that is intended for distribution.
Using the above definition, this does seem to be exactly a store output path (realized derivation output). A store output path is an immutable file or immutable directory of files. The store output paths are the result of building the package outputs (derivation outputs). These store output paths are what is intended for distribution using a command like nix-copy-closure to a remote machine or "nix copy" to a binary cache (or other nix store).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I am finally coming around to what you are looking for. I am thinking too much in the nix way. And need to be thinking in the SLSA model that you presented earlier. So I think your last proposal for the mapping is correct, but maybe change store object to store path. Does that sound good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just reviewed the Nix definitions of store path and store object, and you are correct that is should be store object. I have updated the commit to reflect your proposed mapping. Thanks a lot for walking through this with me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, there are effectively two separate "packages" here, the "source" package (Derivation) and the "binary" package (store object). The same thing goes with Homebrew etc (I assume - I'm unfamiliar with them). Either way, end result looks good to me.
0a59d2c
to
f2c045c
Compare
Change Nix package ecosystem terminology to match definitions of SLSA Package model terminology. Capitalize Nix to match proper name of package ecosystem. Map SLSA Package registry to Nixpkgs (the largest repository of Nix packages) and binary cache. Map SLSA Package name to Derivation name. Map SLSA Package artifact to Derivation or store object. Signed-off-by: Mark Sisson <[email protected]>
f2c045c
to
3d2f843
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all this! I think the end result looks good.
Friendly ping. Can another maintainer approve? ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a NixOS expert but LGTM
Let's go with this. If folks have further suggestions, we can always have another PR. Thanks again, @marksisson! |
Change Nix package ecosystem terminology to match definitions of SLSA Package model terminology. Capitalize Nix to match proper name of package ecosystem. Map SLSA Package registry to Nixpkgs (the largest repository of Nix packages [and also a Nix Flake]) and Flakes (distributed repositories of Nix packages). Map SLSA Package name to attributes of Nixpkgs and Flake outputs. Map SLSA Package artifact to Nix Store Path.