Nix

时间:2016-01-13 14:31:09

标签: nix nixos nixpkgs

我刚刚开始接触Nix,如果我在文档中错过了我的问题的答案,那么道歉。

我想使用Nix设置一个安全的生产机器,其中包含最少的库和可执行文件。我不希望出现任何编译器或其他构建工具,因为这些可能存在安全风险。

当我安装一些软件包时,它们似乎只依赖于最小的运行时依赖项集。例如,如果我安装apache-tomcat-8.0.23,那么我将获得Java运行时(JRE)和包含Tomcat的预构建JAR文件。

另一方面,一些软件包似乎包含一个完整的构建工具链作为依赖项。以另一个基于Java的示例为例,当我安装spark-1.4.0时,Nix下载了包含编译器的Java开发工具包(JDK),并且还提取了Maven构建工具等。

所以,我的问题如下:

  1. Nix包是否在构建和运行时依赖关系之间做出了区分?
  2. 为什么有些软件包看起来依赖于构建工具而其他软件包只需要运行时?这完全取决于包作者如何包装应用程序?
  3. 如果一个软件包包含我不想要的构建依赖项,除了为同一个应用程序设计我自己的替代包装之外,我作为运营商可以做些什么吗?
  4. 非常感谢。

1 个答案:

答案 0 :(得分:24)

  1. 运行时依赖项是构建时依赖项的一个子集,Nix通过扫描生成的输出来自动确定每个构建时依赖项的存储路径的哈希部分。例如,如果使用编译器/nix/store/abcdef...-foo-1.20构建包,则Nix将扫描生成的输出中的所有文件以获取哈希位abcdef...。如果找到了这个哈希,那么假定输出以某种方式引用编译器,因此它是作为运行时依赖项的kepts。但是,如果没有发生该哈希,则生成的输出没有对编译器的引用,因此无法在运行时访问它,因此foo-1.20被视为仅构建时依赖项。

  2. 有些软件包会记录其构建环境的大部分内容,以用于信息/调试目的。例如,Perl存储了用于编译它的工具的每一个细节,所以所有这些存储路径最终都被视为运行时依赖,尽管Perl在运行时实际上并不需要它们,但是Nix不知道:它只知道Perl存储路径引用这些工具。现在,Nixpkgs维护者通常会努力清理它,即通过修剪包含安装中所有这些存储路径的日志文件等,但是可以肯定的是,数据库中仍有大量的软件包尚未优化到那个结束了。

  3. 假设你想要编译一个不依赖于PAM的openssh版本。然后,您可以通过覆盖从表达式中删除构建输入,即用pam替换通常传递给openssh构建函数的null参数。为此,请将以下文件存储在~/.nixpkgs/config.nix

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

    现在运行:

    安装该软件包
    $ nix-env -f "<nixpkgs>" -iA openssh-without-pam