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


14

假设我有一个非常简单的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文件应包含任何有效的Nix表达式(例如,函数或集合)。这意味着NixOS配置文件/etc/nixos/configuration.nix本身就是一个包含Nix表达式的模块。

我也知道,要使另一个模块中的Nix表达式对我正在使用的模块可见,我可以使用内置import函数

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

Answers:


22

Nix表达式

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

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

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

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

所以这意味着在调用时nixos-rebuild switch,某些调用带有包含属性config和的集合的NixOS配置文件中的函数pkgs

进口货

下面的例子./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具有一组属性的调用,其中一些属性是configand pkgs

它发现属性imports返回set里面,所以它的计算结果中的模块,每一个尼克斯表达imports使用相同的参数(包含configpkgs等)。

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

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

为什么没有pkgsconfiguration.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 ]


1
如何合并进口?他们使用recursiveUpdate还是类似的东西?
aij

1
有办法进行有条件进口吗?
CMCDragonkai

1
@CMCDragonkai的值imports只是一个列表,因此您可以有条件地imports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);
向其
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.