Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build versus Runtime Dependencies in Nix

Tags:

nix

nixos

nixpkgs

I am just starting to get to grips with Nix, so apologies if I missed the answer to my question in the docs.

I want to use Nix to setup a secure production machine with the minimal set of libraries and executables. I don't want any compilers or other build tools present because these can be security risks.

When I install some packages, it seems that they depend on only the minimum set of runtime dependencies. For example if I install apache-tomcat-8.0.23 then I get a Java runtime (JRE) and the pre-built JAR files comprising Tomcat.

On the other hand, some packages seem to include a full build toolchain as dependencies. Taking another Java-based example, when I install spark-1.4.0 Nix pulls down the Java development kit (JDK) which includes a compiler, and it also pulls the Maven build tool etc.

So, my questions are as follows:

  1. Do Nix packages make any distinction between build and runtime dependencies?
  2. Why do some packages appear to depend on build tools whereas others only need runtime? Is this all down to how the package author wrapped up the application?
  3. If a package contains build dependencies that I don't want, is there anything that I, as the operator, can do about it except design my own alternative packaging for the same application?

Many thanks.

like image 284
Neil Bartlett Avatar asked Jan 13 '16 14:01

Neil Bartlett


People also ask

What does Nix build do?

nix . nix-build is essentially a wrapper around nix-instantiate (to translate a high-level Nix expression to a low-level store derivation) and nix-store --realise (to build the store derivation). The result of the build is automatically registered as a root of the Nix garbage collector.

Is nix a build system?

Nix is a collection of tools and systems that together form a highly reproducible build system. Nix is also a declarative, largely pure and lazy programming language that you use to design and specify the different build outputs for the Nix build system.

What is a Nix derivation?

Derivations are the building blocks of a Nix system, from a file system view point. The Nix language is used to describe such derivations.

How does Nix package manager work?

Nix is a cross-platform package manager that utilizes a purely functional deployment model where software is installed into unique directories generated through cryptographic hashes. It is also the name of the tool's programming language.


1 Answers

  1. The runtime dependencies are a subset of the build-time dependencies that Nix determines automatically by scanning the generated output for the hash part of each build-time dependencies' store path. For example, if you build a package using the compiler /nix/store/abcdef...-foo-1.20, then Nix will scan all files in the generated output for the hash bit abcdef.... If that hash is found, then the output is assumed to reference the compiler in some way, so it's kepts as a runtime dependency. If that hash does not occur, however, then the generated output has no reference to the compiler and therefore cannot access it at runtime, so foo-1.20 is treated as a build-time-only dependency.

  2. Some packages record large parts of their build environment for informational/debugging purposes. Perl, for example, stores every little detail about the tools used to compile it, so all those store paths end up being treated as runtime dependencies despite the fact that Perl doesn't actually need them at runtime, but Nix can't know: it just knows that the Perl store path references those tools. Now, Nixpkgs maintainers usually make an effort to clean that up, i.e. by pruning the logfile that contains all those store paths from the installation, etc., but for sure there are plenty of packages in the database still that haven't been optimized to that end yet.

  3. Let's assume that you'd like to compile a version of openssh that does not depend on PAM. Then you can remove the build input from the expression by means of an override, i.e. you replace the pam argument that's normally passed to the openssh build function with null. To do that, store the following file in ~/.nixpkgs/config.nix

    {
      packageOverrides = super: let self = super.pkgs; in {
        openssh-without-pam = super.openssh.override {
          pam = null;
        };
      };
    }
    

    and now install that package by running:

    $ nix-env -f "<nixpkgs>" -iA openssh-without-pam
    
like image 199
Peter Simons Avatar answered Oct 08 '22 10:10

Peter Simons