如何将 /etc/nixos/configuration.nix 拆分为单独的模块?

如何将 /etc/nixos/configuration.nix 拆分为单独的模块?

假设我有一个非常简单的NixOS 配置文件:

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = with pkgs; [ emacs gitFull ];
  # SOME STUFF
}

我知道 NixOS 实现了模块系统,模块就是一个.nix文件。每个.nix文件都应包含任何有效的尼克斯表达(例如函数或集合)。这意味着 NixOS 配置文件/etc/nixos/configuration.nix本身就是一个模块,包含 Nix 表达式。

我还知道,为了使另一个模块中的 Nix 表达式对我正在使用的模块可见,我可以使用内置的import功能

我想将系统包的声明(包含emacs和 的列表gitFull)拆分到 file 中packages.nix。如何将 NixOS 配置文件拆分为单独的模块?

答案1

尼克斯表达式

A尼克斯表达就像任何编程语言表达式一样:任何计算结果为值或函数的东西。这种情况下的值也可以是列表或集合。由于 Nix 模块(扩展名为 的文件.nix)可以包含任何 Nix 表达式,因此您会期望 NixOS 配置文件 ( /etc/nixos/configuration.nix) 包含单个 Nix 表达式作为其文件内容。

NixOS 配置文件包含以下形式的 Nix 表达式:

{config, pkgs, ...}: { /* various configuration options */ }

如果你仔细观察,你会发现这是一个功能,因为功能遵循形式pattern: form。您还可以看到它是一个接受集合并返回集合的函数。例如,如果您有一个 function f = {x, y}: {a = x + y;},那么您可以将其称为f {x=1; y=2;}并返回一个 set {a=3;}

因此,这意味着当您调用 时,某些东西会使用必须包含属性和 的nixos-rebuild switch集合来调用 NixOS 配置文件内的函数。configpkgs

进口

以下示例中./hardware-configuration.nix,将包列表提取到单独模块中的简单方法packages.nix是将environment.systemPackages选项取出并放入选项./packages.nix中。imports你的/etc/nixos/configuration.nix看起来像:

{ config, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      # Include the package list.
      ./packages.nix
    ];
  # SOME STUFF
  # SOME STUFF
}

你的/etc/nixos/packages.nix看起来像:

{ pkgs, ... }:
{
  environment.systemPackages = with pkgs; [ emacs gitFull ];
}

这是如何运作的?当您运行 时nixos-rebuild switch,评估 Nix 表达式并决定安装软件包等的过程会调用configuration.nix一组属性,其中一些属性是configpkgs

它在返回的集合中查找属性,因此它会计算包含相同参数(、等)imports的模块中的每个 Nix 表达式。importsconfigpkgs

您必须将pkgs中的函数作为参数(或者,从技术上讲,集合的属性,其本身就是一个参数)packages.nix,因为从 Nix 语言的角度来看,该过程可能会或可能不会调用具有以下集合的函数:包含pkgs.如果没有,运行时您会引用什么属性with pkgs

您还必须有省略号,因为该函数可能会使用其他属性来调用,而不仅仅是pkgs.

pkgs为什么里面没有configuration.nix?您可以拥有它,但如果您不在文件中的任何位置引用它,则可以安全地省略它,因为省略号无论如何都会包含它们。

通过调用外部函数更新属性

另一种方法是创建一个函数,返回一个带有某些属性的集合,以及您将放入其中的该属性的值environment.systemPackages。这是你的configuration.nix

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = import ./packages.nix pkgs;
  # SOME STUFF
}

你的packages.nix

pkgs: with pkgs; [ emacs gitFull ]

import ./packages.nix pkgs意思是:加载并返回 Nix 表达式./packages.nix,因为它是一个函数,所以用参数调用它pkgswith pkgs; [ emacs gitFull ]是一个with 表达式,它将分号之前的表达式的范围带到分号之后的表达式。没有它,那就是[ pkgs.emacs pkgs.gitFull ]

相关内容