如何在nix中记录可重现的配置文件(尤其是来自nix-env)?

时间:2018-05-08 21:16:33

标签: nix

所以,最后开始获得一个稳定的nix环境,我基本上可以完成我的所有开发。万岁!

现在我希望它可以重现,如yarn.lock(对于那些熟悉javascript版本中的npm / yarn)或Pipfile.lock(非常类似于Python)。

基本上我的想法是,无论何时运行nix-env -if my-env.nix,或者在运行此命令之后,我都有办法生成类似的锁文件,如果它是这样的话。从这个锁定文件,我可以完全恢复我的nix配置文件,直到确定的安装配置文件的依赖项和子依赖项的版本。在测试出新的改进之后,可以将其检入git或其他任何内容,因此将保留环境记录。

在我看来,这将是Nix最明显的使用案例之一,而且仅仅使用Docker的主要优势之一(尽管两者并不相互排斥),所以如果我错过了一些,我会道歉相关文件。

2 个答案:

答案 0 :(得分:5)

您可能正在寻找的是shell.nix这样的文件:

let
  pkgs = import (fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f.tar.gz";
    sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
  }) {};
in pkgs.mkShell {
  buildInputs = with pkgs; [
    git
    hello
  ];
}

在调用nix-shell(默认使用当前目录中的shell.nix文件)后,您将进入具有githello特定条件的环境中鉴于nixpkgs修订版。这可以在所有nix用户之间重现(好吧差不多*)。我真的可以推荐使用shell.nix文件进行所有开发。

或者,-r还有一个鲜为人知的nix-env标志,表明

  

- remove-all,-r

     

首先删除所有以前安装的软件包。这相当于首先运行nix-env -e'。*',除了一切都在一个事务中发生。

您可以有效地使用它来替换有状态~/.nix-profile/manifest.nix。创建一个包含以下内容的文件env.nix

let
  pkgs = import <nixpkgs> {};
in {
  inherit (pkgs) git hello;
}

现在运行nix-env -ir env.nix将完全安装githello并删除其他所有内容,因此您可以使用此单个文件重现nix-env安装。要安装其他内容:将其添加到文件并再次运行该命令。你也可以将nixpkgs固定到上面文件中的特定版本,而不关心你的nix-channel设置(也是有状态的)。

修改:也可以从您的频道获取一些软件包以及一些特定的nixpkgs版本:

let
  pkgs = import <nixpkgs> {};
  fixed = import (fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f.tar.gz";
    sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
  }) {};
in {
  inherit (pkgs) git;
  inherit (fixed) hello;
}

*:nix配置,覆盖和您的系统(Linux / Mac)仍然可以影响这一点。使用import <nixpkgs> { config = {}; overlays = []; }进行开发以避免这种情况是个好主意。

答案 1 :(得分:0)

在IRC的人们提出许多建议之后,我能够将以下脚本放在一起,该脚本将nix表达式作为其唯一参数,并复制派生文件并在安装指定环境时在本地记录nixpkgs版本:

#!/bin/bash

if [ -z "$1" ] || [ "${1: -4}" != ".nix" ] || [ ! -f "$1" ]
  then
      echo "No .nix file supplied"
      exit -1
fi

ENV_DRV=$(nix-instantiate "$1")
cp "$ENV_DRV" ./env_backup.drv
chmod u+rw ./env_backup.drv
nix-env --set "$ENV_DRV"


NIXPKGS_VERSION=$(nix-instantiate --eval '<nixpkgs/lib>' -A version)
NIXOS_VERSION=$(nix-instantiate --eval '<nixos/lib>' -A version)

printf "nixpkgs: %s\\nnixos: %s" "$NIXPKGS_VERSION" "${NIXOS_VERSION}" > .nix_versions

警告:您的nix表达式中应包含nix个包,因为我们使用的是nix-env --set

我还没有尝试使用复制的.drv文件,但它需要以某种方式恢复到nix存储中;我主要把它作为最后的手段和调试。输出到.nix_versions应该更有帮助,因为它们包含git commit哈希(在最后一个“。”之后),可用于使用正确的nixpkgs修订版(感谢IRC上的infinisil):

pkgs = import "${(import <nixpkgs> {}).fetchFromGitHub { owner = "NixOS"; repo = "nixpkgs"; rev = "<your revision hash>"; sha256 = "<the hash of the output>"; }}" {}

要填写哈希值,请提供错误的哈希值以获取正确的哈希值,或者只使用以下内容:nix-prefetch-url --unpack github.com/nixos/nixpkgs/archive/<revision>.tar.gz

或者,如果手动检出nixpkgs,你可以这样做:

with import ((builtins.getEnv "HOME") + "/workspace/nixpkgs") { }; # or:
with import "../nixpkgs" { }; # or similar

我还没有用nix-shell测试过这种事情,但希望尽快这样做。