Flakes/ru: Difference between revisions

Unabomberlive (talk | contribs)
Created page with "== Трюки для разработки =="
Golits (talk | contribs)
No edit summary
 
(71 intermediate revisions by 4 users not shown)
Line 1: Line 1:
<languages />
<languages />
<div lang="en" dir="ltr" class="mw-content-ltr">
'''Nix flakes''' is an [https://nixos.org/manual/nix/stable/contributing/experimental-Features.html experimental feature] that was introduced with Nix 2.4 ([https://nixos.org/manual/nix/unstable/release-notes/rl-2.4.html see release notes]).
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
{{Cleanup}}
====Introduction====
 
</div>
'''Nix Flakes''' (Флейки Nix) — это [[Experimental Nix features|экспериментальная функция]], впервые представленная в релизе [[Nix]] 2.4{{Cite manual|nix|development/experimental-features|number=13.8|title=Experimental Features|subsection=xp-feature-flakes|subtitle=flakes}}{{Cite manual|nix|release-notes/rl-2.4|number=14.27|title=Release 2.4 (2021-11-01)}}, которая направлена на решение ряда задач по улучшению экосистемы Nix: Флейки предоставляют единую структуру для Nix-проектов, позволяя фиксировать конкретные версии каждой зависимости, делиться этими зависимостями с помощью lock-файлов и в целом делать запись репродуцируемых Nix-выражений более удобной.
 
Флейк — это каталог, который содержит файл Nix с именем <code>flake.nix</code>, который следует очень конкретной структуре. Флейки вводят похожий на URL синтаксис{{Cite manual|nix|command-ref/new-cli/nix3-flake|number=8.5.17|title=nix flake|subsection=url-like-syntax|subtitle=URL-like syntax}} для указания удалённых ресурсов. Чтобы упростить синтаксис, флейки используют реестр символических идентификаторов{{Cite manual|nix|command-ref/new-cli/nix3-registry|number=8.5.62|title=nix registry}}, что позволяет напрямую ссылаться на ресурсы в следующей форме: <code>github:NixOS/nixpkgs</code>.
 
Флейки также поддерживают фиксацию ссылок и версий, которые затем могут быть запрошены и обновлены программно через inputs{{cite manual|nix|command-ref/new-cli/nix3-flake-lock|number=7.5.19|title=nix flake lock}}{{cite manual|nix|command-ref/new-cli/nix3-flake-info|number=7.5.17|title=nix flake info}}. Кроме того, экспериментальная утилита командной строки принимает flake-ссылки для выражений, которые собирают, выполняют и развёртывают пакеты{{Cite manual|nix|command-ref/new-cli/nix|number=8.5.1|title=nix}}.
 
== Структура flake-файла ==
В простейшем виде flake-файл содержит описание флейка, набор входных зависимостей (inputs) и выход (output). Вы можете сгенерировать шаблонный flake-файл в любой момент с помощью <code>nix flake init</code>. Это создаст в текущей директории файл <code>flake.nix</code>, содержащий примерно следующее:
{{File|3=<nowiki>{
  description = "A very basic flake";


<div lang="en" dir="ltr" class="mw-content-ltr">
  inputs = {
Nix flakes enforce a uniform structure for Nix projects, pin versions of their dependencies in a lock file, and make it more convenient to write reproducible Nix expressions.
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
</div>
  };


<div lang="en" dir="ltr" class="mw-content-ltr">
  outputs = { self, nixpkgs }: {
* A [https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html#description flake] refers to a file-system tree whose root directory contains the Nix file specification called <code>flake.nix</code>.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
    packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello;
* The contents of <code>flake.nix</code> file follow a uniform naming schema for declaring packages and their dependencies in the Nix language.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
    packages.x86_64-linux.default = self.packages.x86_64-linux.hello;
*  Flakes introduce a [https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#flake-references URL-like syntax] for specifying remote sources.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
  };
* To simplify the long URL syntax with shorter names, [https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-registry.html flakes uses a registry] of symbolic identifiers.
}</nowiki>|name=flake.nix|lang=nix}}
</div>
В примере выше вы можете видеть описание, вход (input), указанный как репозиторий GitHub с конкретной веткой (здесь <code>nixos/nixpkgs</code> на ветке <code>nixos-unstable</code>), и выход (output), который использует этот input. Output в этом примере просто определяет, что в флейке есть один пакет для архитектуры x86_64 под именем <code>hello</code>. Даже если output вашего флейка не использует его inputs (что на практике маловероятно), output всё равно должен быть Nix-функцией.
{{Note|Флейки требуют явного указания outputs для каждой архитектуры отдельно. Для дополнительной информации смотрите соответствующий раздел ниже.}}


<div lang="en" dir="ltr" class="mw-content-ltr">
<div class="mw-translate-fuzzy">
* Flakes also allow for locking references and versions that can then be queried and updated programmatically.
=== Конфигурация Nix ===
Можно переопределить глобальную конфигурацию Nix, заданную в файле <code>nix.conf</code>, чтобы оценить работу флейка. Это может быть полезно, например, для установки бинарных кэшей, специфичных для проекта, пока глобальная конфигурация останется нетронутой. Flake-файл может содержать атрибут <code>nixConfig</code> с любыми релевантными настройками. Например, чтобы включить бинарный кэш nix-community, можно добавить:
{{File|3=<nowiki>{
  ...
  nixConfig = {
    extra-substituters = [
      "https://nix-community.cachix.org"
    ];
    extra-trusted-public-keys = [
      "nix-community.cachix.org-1:...="
    ];
}</nowiki>|name=flake.nix|lang=nix}}{{Note|Если вы привыкли настраивать Nix через конфигурацию NixOS, эти опции находятся под <code>nix.settings</code>, а не под <code>nix</code>. Например, вы не сможете указать автоматическую оптимизацию хранилища через <code>nix.optimisation.enable</code>.}}
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* An [https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html experimental command-line interface] accepts flake references for expressions that build, run, and deploy packages.
== Setup ==
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="Enabling_flakes_temporarily"></span>
====Enable flakes temporarily====
<div class="mw-translate-fuzzy">
==== Временно включить поддержку Flakes ====
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div class="mw-translate-fuzzy">
When using any <code>nix</code> command, add the following command-line options:
При использовании любой команды <code>nix</code> добавьте следующие параметры командной строки:
</div>
</div>
<syntaxhighlight lang="shell">
<syntaxhighlight lang="shell">
  --experimental-features 'nix-command flakes'
  --experimental-features 'nix-command flakes'
</syntaxhighlight>
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
====Enable flakes permanently in NixOS====
=== Enabling flakes permanently ===
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="NixOS"></span>
Add the following to the [[Overview_of_the_NixOS_Linux_distribution#Declarative_Configuration system configuration |NixOS configuration]]:
<div class="mw-translate-fuzzy">
====Включить flakes на постоянной основе в NixOS====
</div>
</div>
Добавьте следующее в [[Overview_of_the_NixOS_Linux_distribution#Declarative_Configuration system configuration |Конфигурацию NixOS]]:


<syntaxHighlight lang=nix>
<syntaxHighlight lang=nix>
Line 59: Line 74:
</syntaxHighlight>
</syntaxHighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="Home_Manager"></span>
=====Other Distros, with Home-Manager=====
<div class="mw-translate-fuzzy">
===== В других Дистрибутивах, с Home-Manager =====
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div class="mw-translate-fuzzy">
Add the following to your home-manager config:
Добавьте следующее в свою конфигурацию Home-Manager:
</div>
</div>


Line 70: Line 86:
   nix.settings.experimental-features = [ "nix-command" "flakes" ];
   nix.settings.experimental-features = [ "nix-command" "flakes" ];
</syntaxhighlight>
</syntaxhighlight>
<span id="Nix_standalone"></span>
<div class="mw-translate-fuzzy">
=====Другие Дистрибутивы, без Home-Manager=====
</div>
{{Note | [https://github.com/DeterminateSystems/nix-installer Детерминированный Установщик Nix (Determinate Nix Installer)] включает Flakes по умолчанию.}}
Добавьте следующее в <code>~/.config/nix/nix.conf</code> или <code>/etc/nix/nix.conf</code>:
<syntaxHighlight lang=text>
experimental-features = nix-command flakes
</syntaxHighlight>
<span id="Usage"></span>
<div class="mw-translate-fuzzy">
=== Основное Использование Flake ===
</div>
<div class="mw-translate-fuzzy">
{{Warning | Так как содержимое файлов Flake скопировано в общедоступную папку хранилища Nix, не храните никаких незашифрованных секретов в файлах Flake. Вам следует использовать [[Comparison of secret managing schemes|схемы управления секретами]].}}
</div>
<div class="mw-translate-fuzzy">
Для флейков в репозиториях git, только файлы из рабочего дерева (Working tree) будут скопированы в хранилище
</div>
<div class="mw-translate-fuzzy">
Поэтому если вы используете git для ваших флейков, не забывайте применять <code>git add</code> ко всем файлам репозитория, после того как вы их создаёте
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
=====Other Distros, without Home-Manager=====
=== The nix flakes command ===
{{Main|Nix (command)}}
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
{{Note | The  [https://github.com/DeterminateSystems/nix-installer Determinate Nix Installer] enables flakes by default.}}
The {{ic|nix flake}} subcommand is described in {{Nix Manual|name=command reference page of the Nix manual|anchor=command-ref/new-cli/nix3-flake}}.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Add the following to <code>~/.config/nix/nix.conf</code> or <code>/etc/nix/nix.conf</code>:
This flake produces a single flake output <code>packages</code>. And within that, <code>x86_64-linux</code> is a system-specifc attribute set. And within that, two package [[derivations]] <code>default</code> and <code>hello</code>. You can find outputs with the {{Nix Manual|name=show command|anchor=command-ref/new-cli/nix3-flake-show}} of a flake as shown below:
</div>
</div>


<syntaxHighlight lang=text>
<div lang="en" dir="ltr" class="mw-content-ltr">
experimental-features = nix-command flakes
<syntaxhighlight lang="console">
</syntaxHighlight>
$ nix flake show
└───packages
    └───x86_64-linux
        ├───default: package 'hello-2.12.2'
        └───hello: package 'hello-2.12.2'
</syntaxhighlight>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
===Basic Usage of Flake===
==== Development shells ====
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Before running any nix commands at this point, please note the two warnings below: one for encryption and the other for git.
A <code>devShell</code> is a Nix-provided [[Development_environment_with_nix-shell#nix develop|development environment]] defined within a flake. It lets you declare a reproducible shell environment with the tools, libraries, and environment variables you need for the development of a specific project. This is flake equivalent to defining a <code>nix-shell</code>.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
====Encryption WARNING====
<syntaxhighlight lang="nix">
{
  description = "Example flake with a devShell";
</div>
 
  <div lang="en" dir="ltr" class="mw-content-ltr">
inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
</div>
 
  <div lang="en" dir="ltr" class="mw-content-ltr">
outputs = { self, nixpkgs}:
    let
      system = "x86_64-linux";
      pkgs = import nixpkgs { inherit system; };
    in {
      devShells.x86_64-linux.default = pkgs.mkShell {
        buildInputs = with pkgs; [
          hello
        ];
        shellHook = ''
          echo "Welcome to the devShell!"
        '';
      };
    };
}
</syntaxhighlight>
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
{{Warning | Since contents of flake files are copied to the world-readable Nix store folder, do not put any unencrypted secrets in flake files. You should instead use a [[Comparison of secret managing schemes|secret managing scheme]].}}
To enter the development shell environment:
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
====Git WARNING====
<syntaxhighlight lang="console">
$ nix develop
</syntaxhighlight>
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
For flakes in git repos, only files in the working tree will be copied to the store.
{{note|You don’t need to define a devShell to enter a development shell using nix develop.
If no devShell is defined, nix develop will drop you into an environment containing the default build dependencies of the flake (if any).}}
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Therefore, if you use <code>git</code> for your flake, ensure to <code>git add</code> any project files after you first create them.
==== Build specific attributes in a flake repository ====
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
See also https://www.tweag.io/blog/2020-05-25-flakes/
Running <code>nix build</code> will look in the <code>legacyPackages</code> and <code>packages</code> output attributes for the corresponding [[derivation]] and then your system architecture and build the default output. If you want to specify a build attribute in a flake repository, you can run <code>nix build .#<attr></code>. In the example above, if you wanted to build the <code>packages.x86_64-linux.hello</code> attribute, run:
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
====Generate flake.nix file====
<syntaxHighlight lang=console>
$ nix build .#hello
</syntaxHighlight>
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
To start the basic usage of flake, run the flake command in the project directory:
Likewise, you can specify an attribute with the run command: <code>nix run .#hello</code> and the develop command: <code>nix develop .#hello</code>.
</div>
</div>
<syntaxHighlight lang=text>
nix flake init
</syntaxHighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 143: Line 221:
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
* <code>description</code> это строка описывающая flake.
* <code>description</code> is a string describing the flake.
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 156: Line 232:


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* <code>nixConfig</code> is an attribute set of values which reflect the [https://nixos.org/manual/nix/stable/command-ref/conf-file.html values given to nix.conf]. This can extend the normal behavior of a user's nix experience by adding flake-specific configuration, such as a binary cache.
* <code>nixConfig</code> is an attribute set of values which reflect the [https://nixos.org/manual/nix/stable/command-ref/conf-file.html values given to nix.conf]. This can extend the normal behavior of a user's nix experience by adding flake-specific configuration, such as a [[Binary Cache|binary cache]].
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="Input_schema"></span>
=== Input schema ===
=== Входная схема ===
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 176: Line 251:


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Nixpkgs can be defined using the following code:
[[Nixpkgs]] can be defined using the following code:
</div>
</div>


<code>inputs.nixpkgs.url = "github:NixOS/nixpkgs/<branch name>";</code>
<code>inputs.nixpkgs.url = "github:NixOS/nixpkgs/<branch name>";</code>
Nixpkgs can alternatively also point to an url cached by the NixOS organization:
<code>inputs.nixpkgs.url = "<nowiki>https://nixos.org/channels/nixpkgs-unstable/nixexprs.tar.xz</nowiki>";</code>
In this example the input would point to the `nixpkgs-unstable` channel.


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 210: Line 292:
};
};
</syntaxhighlight>
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
By default, Git submodules in package <code>src</code>'s won't get copied to the nix store, this may cause the build to fail. Flakes in Git repositories can declare that they need Git submodules to be enabled. Since Nix version [https://discourse.nixos.org/t/nix-2-27-0-released/62003 2.27], you can enable submodules by:
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
<syntaxhighlight lang="nix">
  inputs.self.submodules = true;
</syntaxhighlight>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 223: Line 315:
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
В которой:
Where:
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 296: Line 386:


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
==== nix run ====
== Core usage patterns ==
</div>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
When output <code>apps.<system>.myapp</code> is not defined, <code>nix run myapp</code> runs <code><packages or legacyPackages.<system>.myapp>/bin/<myapp.meta.mainProgram or myapp.pname or myapp.name (the non-version part)></code>
</div>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
== Using flakes with stable Nix ==
</div>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
There exists the [https://github.com/edolstra/flake-compat flake-compat] library that you can use to shim <code>default.nix</code> and <code>shell.nix</code> files. It will download the inputs of the flake, pass them to the flake’s <code>outputs</code> function and return an attribute set containing <code>defaultNix</code> and <code>shellNix</code> attributes. The attributes will contain the output attribute set with an extra <code>default</code> attribute pointing to current platform’s <code>defaultPackage</code> (resp. <code>devShell</code> for <code>shellNix</code>).
</div>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
Place the following into <code>default.nix</code> (for <code>shell.nix</code>, replace <code>defaultNix</code> with <code>shellNix</code>) to use the shim:
</div>
 
<syntaxHighlight lang=nix>
(import (
  fetchTarball {
    url = "https://github.com/edolstra/flake-compat/archive/12c64ca55c1014cdc1b16ed5a804aa8576601ff2.tar.gz";
    sha256 = "0jm6nzb83wa6ai17ly9fzpqc40wg1viib8klq8lby54agpl213w5"; }
) {
  src =  ./.;
}).defaultNix
</syntaxHighlight>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
You can also use the lockfile to make updating the hashes easier using <code>nix flake lock --update-input flake-compat</code>. Add the following to your <code>flake.nix</code>:
</div>
</div>
<syntaxHighlight lang=nix>
  inputs.flake-compat = {
    url = "github:edolstra/flake-compat";
    flake = false;
  };
</syntaxHighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
and add <code>flake-compat</code> to the arguments of <code>outputs</code> attribute. Then you will be able to use <code>default.nix</code> like the following:
=== Making your evaluations pure ===
</div>
</div>
<syntaxhighlight lang="nix">
(import (
  let
    lock = builtins.fromJSON (builtins.readFile ./flake.lock);
    nodeName = lock.nodes.root.inputs.flake-compat;
  in
  fetchTarball {
    url =
      lock.nodes.${nodeName}.locked.url
        or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.${nodeName}.locked.rev}.tar.gz";
    sha256 = lock.nodes.${nodeName}.locked.narHash;
  }
) { src = ./.; }).defaultNix
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
== Accessing flakes from Nix expressions ==
Nix flakes are evaluated in a pure evaluation mode, meaning that access to the external environment is restricted to ensure reproducibility. To maintain purity when working with flakes, consider the following:
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
If you want to access a flake from within a regular Nix expression on a system that has flakes enabled, you can use something like <code>(builtins.getFlake "/path/to/directory").packages.x86_64-linux.default</code>, where 'directory' is the directory that contains your <code>flake.nix</code>.
* {{Nixpkgs Manual|name=fetchurl|anchor=#sec-pkgs-fetchers-fetchurl-inputs}} and {{Nixpkgs Manual|name=fetchzip|anchor=#sec-pkgs-fetchers-fetchzip-inputs}} require a <code>sha256</code> argument to be considered pure.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
== Making your evaluations pure ==
* <code>builtins.currentSystem</code> is non-hermetic and impure as it reflects the host system performing the evauluation. This can usually be avoided by passing the system (i.e., x86_64-linux) explicitly to derivations requiring it.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Nix flakes run in pure evaluation mode, which is underdocumented. Some tips for now:
*  <code>builtins.getEnv</code> is also impure. Avoid reading from environment variables and likewise, do not reference files outside of the flake's directory.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* fetchurl and fetchtar [https://github.com/NixOS/nix/blob/36c4d6f59247826dde32ad2e6b5a9471a9a1c911/src/libexpr/primops/fetchTree.cc#L201 require] a sha256 argument to be considered pure.
=== Defining a flake for multiple architectures ===
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* builtins.currentSystem is non-hermetic and impure. This can usually be avoided by passing the system (i.e., x86_64-linux) explicitly to derivations requiring it.
Flakes force you to specify a program for each supported architecture. An example below shows how to write a flake that targets multiple architectures.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* Imports from channels like <code><nixpkgs></code> can be made pure by instead importing from the <code>output</code> function in <code>flake.nix</code>, where the arguments provide the store path to the flake's inputs:
</div>
<syntaxhighlight lang="nix">
outputs = { self, nixpkgs, ... }:
  {
    nixosConfigurations.machine = nixpkgs.lib.nixosSystem {
      modules = [
        "${nixpkgs}/nixos/modules/<some-module>.nix"
        ./machine.nix
      ];
    };
  };
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
== The nix flakes command ==
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
The {{ic|nix flake}} subcommand is described in [https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html command reference page of the unstable manual].
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
== Install packages with `nix profile` ==
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
[https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-profile-install.html <code>nix profile install</code> in the manual]
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
== Using nix flakes with NixOS ==
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
{{Ic|nixos-rebuild switch}} will read its configuration from <code>/etc/nixos/flake.nix</code> if it is present.
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
A basic nixos flake.nix could look like this:
</div>
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{
{
   inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
   description = "A flake targeting multiple architectures";
  outputs = { self, nixpkgs }: {
    # replace 'joes-desktop' with your hostname here.
    nixosConfigurations.joes-desktop = nixpkgs.lib.nixosSystem {
      modules = [ ./configuration.nix ];
    };
  };
}
</syntaxhighlight>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
If you want to pass on the flake inputs to external configuration files, you can use the <code>specialArgs</code> attribute:
</div>
</div>


<syntaxhighlight lang="nix">
  <div lang="en" dir="ltr" class="mw-content-ltr">
{
inputs = {
  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  inputs.home-manager.url = github:nix-community/home-manager;
 
  outputs = { self, nixpkgs, ... }@inputs: {
    nixosConfigurations.fnord = nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [ ./configuration.nix ];
    };
   };
   };
}
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
Then, you can access the flake inputs from the file <code>configuration.nix</code> like this:
</div>
<syntaxhighlight lang="nix">
{ config, lib, inputs, ... }: {
  # do something with home-manager here, for instance:
  imports = [ inputs.home-manager.nixosModules.default ];
  ...
}
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
{{Ic|nixos-rebuild}} also allows to specify different flake using the <code>--flake</code> flag (# is optional):
</div>
<syntaxhighlight lang="console">
$ sudo nixos-rebuild switch --flake .
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
By default nixos-rebuild will use the currents system hostname to lookup the right nixos configuration in <code>nixosConfigurations</code>. You can also override this by using appending it to the flake parameter:
</div>
<syntaxhighlight lang="console">
$ sudo nixos-rebuild switch --flake /etc/nixos#joes-desktop
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
To switch a remote host you can use:
</div>
<syntaxhighlight lang="bash">
$ nixos-rebuild --flake .#mymachine \
  --target-host mymachine-hostname \
  --build-host mymachine-hostname --fast \
  switch
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
{{warning|Remote building seems to have an issue that's [https://github.com/NixOS/nixpkgs/issues/134952#issuecomment-1367056358 resolved by setting the <code>--fast</code> flag].}}
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
  <div lang="en" dir="ltr" class="mw-content-ltr">
== Pinning the registry on NixOS ==
outputs = { self, nixpkgs }: let
</div>
    systems = [ "x86_64-linux" "aarch64-linux" ];
 
    forAllSystems = f: builtins.listToAttrs (map (system: {
<syntaxhighlight lang="nix">
      name = system;
{ inputs, ... }:
      value = f system;
{
    }) systems);
nix.registry = {
  in {
     nixpkgs.flake = inputs.nixpkgs;
    packages = forAllSystems (system: let
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      hello = pkgs.hello;
      default = pkgs.hello;
     });
   };
   };
}
}
</syntaxhighlight>
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
To make sure the registry entry is "locked", use the following:
</div>
</div>
<syntaxHighlight lang=nix>
  nix.registry = {
    nixpkgs.to = {
      type = "path";
      path = pkgs.path;
      narHash = builtins.readFile
          (pkgs.runCommandLocal "get-nixpkgs-hash"
            { nativeBuildInputs = [ pkgs.nix ]; }
            "nix-hash --type sha256 --sri ${pkgs.path} > $out");
    };
  };
</syntaxHighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
This has the unfortunate side-effect of requiring import-from-derivation and slowing down build times, however it may greatly speed up almost every eval. Full-time flakes users may be able to just use <code>narHash = pkgs.narHash</code>.
You can also use third-parties projects like [[Flake Utils|flake-utils]] or [[Flake Parts|flake-parts]] that automatically provide code to avoid this boilerplate. To avoid re-defining the program multiple times, refer to [[Flake Utils#Defining a flake for multiple architectures]]
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
== Super fast nix-shell ==
=== Using overlays ===
</div>
</div>  


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
A feature of the nix Flake edition is that Nix evaluations are cached.
To use [[Overlays]] with flakes, refer to [[Overlays#In a Nix flake]] page.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="Enable_unfree_software"></span>
Let’s say that your project has a <code>shell.nix</code> file that looks like this:
<div class="mw-translate-fuzzy">
== Включить несвободное ПО ==
</div>
</div>
<syntaxhighlight lang="nix">
{
  pkgs ? import <nixpkgs> { },
}:
pkgs.mkShell {
  packages = [ pkgs.nixfmt ];
  shellHook = ''
    # ...
  '';
}
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Running nix-shell can be a bit slow and take 1-3 seconds.
To allow for [[Unfree software|unfree software]] in a flake project, you need to explicitly allow it by setting <code>config.allowUnree = true;</code> when importing Nixpkgs.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Now create a <code>flake.nix</code> file in the same repository:
</div>
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{
{
   inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
   inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
 
   outputs = { self, nixpkgs, flake-compat }:
   outputs =
     let
    { nixpkgs, ... }:
       system = "x86_64-linux";
     {
       pkgs = import nixpkgs { inherit system; config.allowUnfree = true;};
       /*
    in {
        This example assumes your system is x86_64-linux
      ...
        change as neccesary
      */
       devShells.x86_64-linux =
        let
          pkgs = nixpkgs.legacyPackages.x86_64-linux;
        in
        {
          default = pkgs.mkShell {
            packages = [ pkgs.hello ];
          };
        };
     };
     };
}
}
}
</syntaxhighlight>
</syntaxhighlight>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
( If you're in a git repository run `git add flake.nix` so that Nix recognizes it. )
== NixOS configuration with flakes ==
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
And finally, run <code>nix develop</code>. This is what replaces the old nix-shell invocation.
It is possible to manage a [[NixOS]] system configuration using flakes, gaining the benefits of reproducible, declarative inputs and streamlined updates.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Exit and run again, this command should now be super fast.
For details and examples, see [[NixOS system configuration#Defining NixOS as a flake]].
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="Development_tricks"></span>
{{warning|TODO: there is an alternative version where the defaultPackage is a pkgs.buildEnv that contains all the dependencies. And then nix shell is used to open the environment.}}
== Трюки для разработки ==
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<span id="Automatically_switch_nix_shells_with_direnv"></span>
=== Automatically switch nix shells with nix-direnv ===
<div class="mw-translate-fuzzy">
=== Автоматическое переключение оболочек nix с nix-direnv ===
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
You can easily switch nix shells when you cd into different projects with [https://github.com/nix-community/nix-direnv nix-direnv].
It is possible to automatically activate different Nix shells when navigating between project directories by using [[Direnv]]. Additional Nix integration with Direnv can be achieved with [https://github.com/nix-community/nix-direnv nix-direnv].
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
== Pushing Flakes to Cachix ==
=== Pushing Flakes to Cachix ===
</div>
</div>


Line 620: Line 515:


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
To push ''all'' flake outputs automatically, checkout [https://github.com/srid/devour-flake#usage devour-flake].
=== Flake support in projects without flakes ===
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
== Build specific attributes in a flake repository ==
The [https://github.com/edolstra/flake-compat flake-compat] library provides a compatibility layer that allows projects using traditional <code>default.nix</code> and <code>shell.nix</code> files to operate with flakes. For more details and usage examples, see the [[Flake Compat]] page.
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
When in the repository top-level, run <code>nix build .#<attr></code>. It will look in the <code>legacyPackages</code> and <code>packages</code> output attributes for the corresponding derivation.
Another project that allows consuming flakes from non-flake projects is [https://github.com/fricklerhandwerk/flake-inputs flake-inputs].
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Eg, in nixpkgs:
=== Accessing flakes from Nix expressions ===
</div>
 
<syntaxHighlight lang=console>
$ nix build .#hello
</syntaxHighlight>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
=== Building flakes from a Git repo url with submodules ===
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
As per nix 2.9.1, git submodules in package <code>src</code>'s won't get copied to the nix store, this may cause the build to fail. To workaround this, use:
If you want to access a flake from within a regular Nix expression on a system that has flakes enabled, you can use something like <code>(builtins.getFlake "/path/to/directory").packages.x86_64-linux.default</code>, where 'directory' is the directory that contains your <code>flake.nix</code>.
</div>
</div>
<syntaxhighlight lang="console">
nix build '.?submodules=1#hello'
</syntaxhighlight>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
See: https://github.com/NixOS/nix/pull/5434
=== Efficiently build multiple flake outputs ===
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
== Importing packages from multiple nixpkgs branches ==
To push ''all'' flake outputs automatically, checkout [https://github.com/srid/devour-flake#usage devour-flake].
</div>
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
A NixOS config flake could be as follows:
</div>
<syntaxhighlight lang="nix">
{
  description = "NixOS configuration with two or more channels";
inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
    nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs =
    { nixpkgs, nixpkgs-unstable, ... }:
    {
      nixosConfigurations."<hostname>" = nixpkgs.lib.nixosSystem {
        modules = [
          {
            nixpkgs.overlays = [
              (final: prev: {
                unstable = nixpkgs-unstable.legacyPackages.${prev.system};
                # use this variant if unfree packages are needed:
                # unstable = import nixpkgs-unstable {
                #  inherit system;
                #  config.allowUnfree = true;
                # };
              })
            ];
          }
          ./configuration.nix
        ];
      };
    };
}
</syntaxhighlight>
<syntaxhighlight lang="nix">
# NixOS configuration.nix, can now use "pkgs.package" or "pkgs.unstable.package"
{ pkgs, ... }:
{
  environment.systemPackages = [
    pkgs.firefox
    pkgs.unstable.chromium
  ];
  # ...
}
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
If the variable <code>nixpkgs</code> points to the flake, you can also define <code>pkgs</code> with overlays with:
</div>
<syntaxhighlight lang="nix">
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ /*the overlay in question*/ ]; };
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
== Getting ''Instant'' System Flakes Repl ==
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
How to get a nix repl out of your system flake:
</div>
<syntaxhighlight lang="text">
$ nix repl
nix-repl> :lf /path/to/flake
Added 18 variables.
nix-repl> nixosConfigurations.myHost.config.networking.hostName
"myHost"
</syntaxhighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
However, this won't be instant upon evaluation if any file changes have been done since your last configuration rebuild. Instead, if one puts:
</div>
<syntaxHighlight lang=nix>
nix.nixPath = let path = toString ./.; in [ "repl=${path}/repl.nix" "nixpkgs=${inputs.nixpkgs}" ];
</syntaxHighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
In their system <code>flake.nix</code> configuration file, and includes the following file in their root directory flake as <code>repl.nix</code>:
</div>
<syntaxHighlight lang=nix>
let
  flake = builtins.getFlake (toString ./.);
  nixpkgs = import <nixpkgs> { };
in
{ inherit flake; }
// flake
// builtins
// nixpkgs
// nixpkgs.lib
// flake.nixosConfigurations
</syntaxHighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
(Don't forget to <code>git add repl.nix && nixos-rebuild  switch --flake "/etc/nixos"</code>)
Then one can run (or bind a shell alias):
</div>
<syntaxHighlight lang=bash>
source /etc/set-environment && nix repl $(echo $NIX_PATH | perl -pe 's|.*(/nix/store/.*-source/repl.nix).*|\1|')</syntaxHighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
This will launch a repl with access to <code>nixpkgs</code>, <code>lib</code>, and the <code>flake</code> options in a split of a second.
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
An alternative approach to the above shell alias is omitting <code>repl</code> from <code>nix.nixPath</code> and creating a shell script:
</div>
<syntaxHighlight lang=nix>
nix.nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
environment.systemPackages = let
  repl_path = toString ./.;
  my-nix-fast-repl = pkgs.writeShellScriptBin "my-nix-fast-repl" ''
    source /etc/set-environment
    nix repl "${repl_path}/repl.nix" "$@"
  '';
in [
  my-nix-fast-repl
];
</syntaxHighlight>
<div lang="en" dir="ltr" class="mw-content-ltr">
== Enable unfree software ==
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
Refer to [[Unfree software|Unfree Software]].
</div>
<span id="Development_tricks"></span>
== Трюки для разработки ==


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
Line 829: Line 571:


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
When a git folder exists, flake will only copy files added in git to maximize reproducibility (this way if you forgot to add a local file in your repo, you will directly get an error when you try to compile it). However, for development purpose you may want to create an alternative flake file, for instance containing configuration for your preferred editors as described [https://discourse.nixos.org/t/local-personal-development-tools-with-flakes/22714/8 here]… of course without committing this file since it contains only your own preferred tools. You can do so by doing something like that (say for a file called <code>extra/flake.nix</code>):
When a [[git]] folder exists, flake will only copy files added in git to maximize reproducibility (this way if you forgot to add a local file in your repo, you will directly get an error when you try to compile it). However, for development purpose you may want to create an alternative flake file, for instance containing configuration for your preferred editors as described [https://discourse.nixos.org/t/local-personal-development-tools-with-flakes/22714/8 here]… of course without committing this file since it contains only your own preferred tools. You can do so by doing something like that (say for a file called <code>extra/flake.nix</code>):
</div>
</div>


Line 874: Line 616:
<span id="See_also"></span>
<span id="See_also"></span>
== См. также ==
== См. также ==
<div lang="en" dir="ltr" class="mw-content-ltr">
=== Official sources ===
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://nix.dev/concepts/flakes Flakes] - nix.dev
* [https://nix.dev/concepts/flakes Flakes] - nix.dev
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html Nix flake command reference manual] - Many additional details about flakes, and their parts.
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://github.com/NixOS/nix/blob/master/src/nix/flake.md spec describing flake inputs in more detail]
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://github.com/NixOS/rfcs/pull/49 RFC 49] (2019) - Original flakes specification
* [https://github.com/NixOS/rfcs/pull/49 RFC 49] (2019) - Original flakes specification
</div>
<div lang="en" dir="ltr" class="mw-content-ltr">
=== Guides ===
</div>
</div>


Line 912: Line 670:


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html Nix flake command reference manual] - Many additional details about flakes, and their parts.
* [https://www.youtube.com/watch?v=QXUlhnhuRX4&list=PLgknCdxP89RcGPTjngfNR9WmBgvD_xW0l Nix flakes 101: Introduction to nix flakes] (Jörg Thalheim, 2020) YouTube video
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://www.youtube.com/watch?v=QXUlhnhuRX4&list=PLgknCdxP89RcGPTjngfNR9WmBgvD_xW0l Nix flakes 101: Introduction to nix flakes] (Jörg Thalheim, 2020)
=== Useful flake modules ===
</div>
 
<div lang="en" dir="ltr" class="mw-content-ltr">
* [[Flake Utils|flake-utils]]: Library to avoid some boiler-code when writing flakes
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://github.com/NixOS/nix/blob/master/src/nix/flake.md spec describing flake inputs in more detail]
* [[Flake Parts|flake-parts]]: Library to help write modular and organized flakes
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://github.com/numtide/flake-utils flake-utils: Library to avoid some boiler-code when writing flakes]
* [[Flake Compat|flake-compat]]: A compatibility layer for flakes
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://zimbatm.com/NixFlakes/#direnv-integration zimbat's direnv article]
* [https://github.com/nix-community/todomvc-nix building Rust and Haskell flakes]
</div>
</div>


<div lang="en" dir="ltr" class="mw-content-ltr">
<div lang="en" dir="ltr" class="mw-content-ltr">
* [https://github.com/nix-community/todomvc-nix building Rust and Haskell flakes]
{{references}}
</div>
</div>


[[Category:Software]]
[[Category:Software]]
[[Category:Nix]]
[[Category:Nix]]
[[Category:Nix Language]]
[[Category:Flakes]]
[[Category:Flakes]]