Як розділити /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) геть у файл packages.nix. Як розділити файл конфігурації NixOS на окремі модулі?

Відповіді:


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;}, ви можете назвати її як f {x=1; y=2;}і повернути набір {a=3;}.

Отже, це означає, що при виклику nixos-rebuild switchщось викликає функцію всередині файлу конфігурації NixOS з набором, який повинен містити атрибути configта 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з набором атрибутів, деякі з яких є configі pkgs.

Він знаходить атрибут importsвсередині повертається набору, так що він оцінює кожен вираз Nix в модулях , які importsутримуються з тими ж аргументами ( config, pkgs, і т.д.).

Ви повинні мати 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і, оскільки це функція, викликайте його аргументом pkgs. with pkgs; [ emacs gitFull ]є з-виразом , він приводить область виразу перед крапкою з комою до виразу після крапки з комою. Без нього було б [ pkgs.emacs pkgs.gitFull ].


1
Як зливають імпорт? Вони використовують рекурсивнеUpdate чи щось подібне?
аїй

1
Чи є спосіб зробити умовний імпорт?
CMCDragonkai

1
@CMCDragonkai значення - importsце лише список, тому ви можете додавати елементи до цього умовно, наприкладimports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);
Warbo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.