Nix是一个软件包管理器,可以让您对软件依赖关系和构建过程有一个更确定的视图。其最大的缺点之一是,关于使用Nix的项目应该如何协同工作,几乎没有约定。它';这就像有一个构建系统,但也必须配置系统来运行自己的软件。这可能意味着从项目中复制一个NixOS模块#39;s git repo,编写自己的或更多。与此相反,Nixflakes定义了一组约定,用于如何构建、运行、集成和部署软件,而无需依赖外部工具(如Niv或Lorri)来帮助您以轻松的方式完成基本任务。
这将是一系列的帖子,它们将建立在彼此的基础上。这篇帖子将介绍Nix flakes,并作为";我为什么要在乎" Style概述了如何使用薄片,而无需太多细节。其中大多数人会得到单独的帖子(有些帖子不止一个)。
在我看来,以下是你应该关心尼克斯的一些重要原因:
进入Nix最让人恼火的地方之一是设置项目;这不完全是一门有定义的科学。Nix配置往往会有机地增长,对于那些没有';我不能启动这个项目。Nix flakes通过做以下几件事来帮助解决这个问题:
定义一片雪花。以尼克斯为中心";枢纽和#34;为了你的项目';的依赖项、公开的软件包、NixOS配置模块等等。
提供一组模板,以便轻松启动项目。想象一下类似于约曼的东西,但它直接内置于尼克斯。你也可以在flake中定义自己的模板。尼克斯。
作为一个例子,我们将用这篇文章的其余部分来帮助解释它,让';让我们用Go模板做一个Go项目。首先,您需要在您的机器上启用Blenix薄片。如果您使用的是NixOS,请将其添加到您的配置中。nix文件:
如果你不在NixOS上,你需要编辑~/。config/nix/nix。Conver/etc/nix/nix。conf并添加以下行:
<;玛拉>;您可能需要在此处重新启动Nix守护进程,但如果您不确定Nix是如何在非NixOS机器上设置的,请随时完全重新启动计算机。
现在转到一个临时文件夹,运行以下命令创建一个文件夹,并从模板创建一个新的薄片:
{description=";一个简单的Go包";#Nixpkgs/NixOS版本要使用。inputs.Nixpkgs.url=";Nixpkgs/NixOS-21.11";#outputs={self,Nixpkgs}:让#生成一个用户友好的版本号。版本=内置。子字符串0 8 self。最后修改日期要支持的系统类型。supportedSystems=[";x86_64-linux";";x86_64-darwin";";aarch64-linux";";aarch64-darwin";]帮助函数生成属性集#39;{x86_64-linux=f";x86_64-linux";…}'. forAllSystems=nixpkgs。lib。genAttrs支持的系统已为受支持的系统类型实例化NIXPKG。nixpkgsFor=forAllSystems(系统:import nixpkgs{inherit system;});在{#中为所选系统类型提供一些二进制软件包。软件包=forAllSystems(系统:let pkgs=nixpkgsFor.${system};在{go hello=pkgs.buildGoModule{pname=";go hello";#inherit version;#在';nix develop';中,我们不需要nix store中的源代码树的副本。src=./.#此哈希锁定此包的依赖项。这是#必要的,因为go需要网络访问才能解决#VCS。请参阅https://www.tweag.io/blog/2021-03-04-gomod2nix/关于#细节。通常情况下,用户可以使用假sha256构建,并依赖原生Go#机制来告诉您哈希应该是什么,或者确定它应该是什么#34;带外";使用其他工具(如gomod2nix)。#首先,建议设置此值,但必须记住,当依赖项发生变化时,要使用此哈希值#vendorSha256=pkgs。lib。假药256;供应商HA256=#34;sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo=&';nix build';。如果#flake只提供一个包,或者有一个清晰的#34;主要的";#包裹defaultPackage=forAllSystems(system:self.packages.${system}.go hello);};}
这定义了macOS和Linux上支持的用于64位x86处理器和64位ARM处理器的单Go包。
<;玛拉>;在实践中,这个价差应该覆盖所有的主要目标';我们需要关注本地开发和云部署。
{description=";一个简单的Go包";inputs.nixpkgs.url=";nixpkgs/nixos-21.11";outputs={self,nixpkgs}:{packages={…};defaultPackage={…};};}
<;卡迪>;注意:在本文的其余部分(以及系列文章)中,当我提到A";薄片输出";,我指的是你的雪花的输出属性中的一个属性。尼克斯。与#34相同;薄片输入";参考雪花的输入属性。尼克斯。
当您早些时候运行nix build时,它默认为在defaultPackage中构建包。您还可以通过运行以下命令来构建go hello包:
标准的默认软件包意味着您可以更轻松地构建软件,而无需阅读要构建的文件的文档。nix build只会起作用™️.
此外,还可以将包公开为应用程序。这使您可以简化上述nix构建和测试/result/bin/go hello循环到一个nix run命令中。打开薄片。关闭你最喜欢的编辑器,让';s将go hello配置为默认应用程序:
<;玛拉>;URL路径的额外部分是用来做什么的?那是gitbranch吗?
<;卡迪>;是的,您可以使用该语法设置Nix应该从中构建的git分支。默认情况下,它将使用默认分支(通常为main),但有时需要指定分支或直接提交。
尼克斯和#39;s的超能力是以声明方式管理项目的开发环境的能力,这样您就可以确保项目中的每个人都在使用相同的工具。
<;卡迪>;我在我所有的项目中都使用了它,以至于当我在项目文件夹之外时,我没有任何可用的开发工具。
Flakes能够使用devShell flake输出指定这一点。你可以把它加到你的薄片上。尼克斯:用这个:
#defaultApp devShell=forAllSystems(系统:let pkgs=nixpkgsFor.${system};在pkgs.mkShell中{buildInputs=with pkgs;[go gopls goimports go tools];});
<;玛拉>;我认为这是一个基本的GO开发环境。它包括标准工具,如语言服务器、用于更好格式化的goimports和类似staticcheck的工具。如果你在工作中定期使用静态检查,如果你觉得多米尼克有用的话,请考虑把它扔掉几个月。这有助于项目更加自我维持。
然后随心所欲地攻击你的项目。你可以把这个git回购发送给朋友,他们也会有相同的设置。
现在让';让我们来谈谈投入。片状输入允许您将外部依赖项添加到项目中。例如,让';让我们看看nixpkgs输入:
这定义了应用于项目的NIXPKG的版本。该模板默认为NixOS 21.11';s版本的nixpkgs,但我们可以将其升级为nixos不稳定,方法是将其更改为:
然后我们可以运行nix flake update,然后运行nix develope,看看我们运行的是一个更新版本的Go:
$nix flake update警告:正在更新锁文件'/home/cadey/tmp/gohello/flake。锁';:•更新输入';尼克斯帕克斯';:'github:NixOS/nixpkgs/77aa71f66fd05d9e7b7d1c084865d703a8008ab7和#39;(2022-01-19) → 'github:NixOS/nixpkgs/2128d0aa28edef51fd8fef38b132ffc0155595df';(2022-02-16)$nix开发[[受电子邮件保护]:~/tmp/gohello]$go版本go版本go1。17.7 linux/amd64
这还允许您引入其他Nix flakes项目,例如my CSS framework Xess:
<;卡迪>;默认情况下,当您使用Nix flakes拉入另一个项目时,它将该项目视为一个完全独立的宇宙,并且只与该flake的输出交互。这意味着它可以拉入自己版本的nixpkgs,它拥有的每个依赖项都可以拉入自己版本的nixpkgs,反之亦然。通过制作Xess和#39;nixpkgs的输入遵循我们自己的输入,我们说";我知道这可能不兼容,但请改用这个版本的nixpkgs";。这可以帮助有很多投入的大型项目(例如,有太多一次性项目的人进行的nixos configs回购)更快地评估和构建。Nixflakes确实有一个缓存的计算器,但它仍然有助于从一开始就避免这个问题。
或者任何你想要的!一个有用的库是flake utils,它可以帮助您简化flake。nix和摆脱那些丑陋的forAllSystems和nixpkgsFor flake中的函数。禁止默认使用此帖子。有关使用此库的薄片的示例,请参见此薄片。住在#xeserv的IRCbot的nix。
通常,您需要在Nix守护进程中启用Nix薄片来利用它们。当你能做到这一点时,这很好,但有时你';我们需要在不启用雪花的情况下为人们提供服务。当需要将Nix flakes项目中的一个项目转换为未启用flakes的项目时,可能会发生这种情况。有一个名为flake compat的图书馆可以让这一切变得简单。
(导入(让lock=builtins.fromJSON(builtins.readFile./flake.lock);在fetchTarball{url=";https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake compat.locked.rev}。焦油gz";;sha256=锁。节点。片状同胞。锁上了。narHash;}){src=./;})。defaultNix
(导入(让lock=builtins.fromJSON(builtins.readFile./flake.lock);在fetchTarball{url=";https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake compat.locked.rev}。焦油gz";;sha256=锁。节点。片状同胞。锁上了。narHash;}){src=./;})。shellNix
Nix flakes本机支持将私有git存储库作为输入。这在尝试构建你不需要的软件时很有用;I don’我不想对外开放。要使用私人回购,您的flake输入URL应该如下所示:
<;卡迪>;我';我很确定你可以在flakes之外使用私人git回购协议,但我一直不清楚你最终会怎么做。
对我来说,最大的问题是它可以让你把NixOS模块嵌入到薄片中。这使您可以在定义软件的位置旁边定义软件的系统配置,从而将其作为一个单元发货。使用它,你可以把安装软件变成将其添加到系统中的一件事';s flake,添加模块,然后启用要启用的设置。
尼克松模块。bot={config,lib,…}{options.within.services.mara-bot.enable=lib.mkEnableOption";enable-mara-bot";config=lib.mkIf-config.within.services.mara-bot.enable{users.groups.mara-bot={};用户。用户。mara bot={createHome=true;isSystemUser=true;home=";/var/lib/mara bot";group=";mara bot";};系统化。服务。mara bot={wantedBy=[";多用户。target";];环境RUST_LOG=";塔http=debug,info";;unitConfig。ConditionPathExists="/var/lib/mara bot/config。亚马尔";;serviceConfig={User=";mara bot";Group=";mara bot";Restart=";always";WorkingDirectory=";/var/lib/mara bot";ExecStart=";${self.defaultPackage./宾/马拉";};};};};};
这里最重要的部分是起点。它指向湖外';s的默认包(希望在其中定义bot';的代码),然后由systemd管理。
我计划用它来彻底简化我的nixos配置回购协议。现在,它有很多特定于项目的代码,如果我能将这些代码转移到相关的项目中,我可以从myconfigs repo的核心中删除很多代码。
最后,Nix flakes通过在构建步骤嵌入系统,让您可以看到系统的配置版本。通常,NixOS允许您通过NixOS版本——json查看以下信息:
您有NixOS版本和nixpkgs哈希。这并不意味着';但是,我不能告诉你正在运行什么配置或关于它的任何事情。但是,使用flakesyou可以将配置的git哈希嵌入到系统配置中:
以上每一个主题都有很多内容要讨论。我';我只是对它们做了一个非常高层次的概述,同时我了解了更多信息,并通过myNixOS配置零碎地迁移到了薄片上。这也给了我一个机会来清理东西,从我的尼克松配置中咀嚼出很多脂肪。准备好后会有更多。
本文发布在M02 21 2022上。自公布以来,事实和情况可能发生了变化。如果有问题或不清楚的地方,请在下结论之前联系我。