mirror of
https://github.com/ryan4yin/nixos-and-flakes-book.git
synced 2024-11-28 11:04:09 +01:00
refactor: divide nixos-with-flakes-enabled into several sections to make it easier to read and find (#132)
This commit is contained in:
parent
cb4941ee44
commit
5410d170a3
@ -186,6 +186,14 @@ function themeConfigEnglish() {
|
||||
text: "NixOS with Flakes Enabled",
|
||||
link: "/nixos-with-flakes/nixos-with-flakes-enabled.md",
|
||||
},
|
||||
{
|
||||
text: "NixOS's flake.nix Explained",
|
||||
link: "/nixos-with-flakes/nixos-flake-configuration-explained.md",
|
||||
},
|
||||
{
|
||||
text: "The combination ability of Flakes and Nixpkgs module system",
|
||||
link: "/nixos-with-flakes/nixos-flake-and-module-system.md",
|
||||
},
|
||||
{
|
||||
text: "Adding Custom Cache Servers",
|
||||
link: "/nixos-with-flakes/add-custom-cache-servers.md",
|
||||
@ -380,6 +388,14 @@ function themeConfigChinese() {
|
||||
text: "使用 Flakes 管理 NixOS",
|
||||
link: "/zh/nixos-with-flakes/nixos-with-flakes-enabled.md",
|
||||
},
|
||||
{
|
||||
text: "NixOS 的 flake.nix 内容详解",
|
||||
link: "/zh/nixos-with-flakes/nixos-flake-configuration-explained.md",
|
||||
},
|
||||
{
|
||||
text: "Flakes 的组合能力与 Nixpkgs 模块系统",
|
||||
link: "/zh/nixos-with-flakes/nixos-flake-and-module-system.md",
|
||||
},
|
||||
{
|
||||
text: "添加自定义缓存服务器",
|
||||
link: "/zh/nixos-with-flakes/add-custom-cache-servers.md",
|
||||
@ -414,7 +430,7 @@ function themeConfigChinese() {
|
||||
{ text: "Overriding", link: "/zh/nixpkgs/overriding.md" },
|
||||
{ text: "Overlays", link: "/zh/nixpkgs/overlays.md" },
|
||||
{
|
||||
text: "多 Nixpkgs 实例",
|
||||
text: "多 Nixpkgs 实例的妙用",
|
||||
link: "/zh/nixpkgs/multiple-nixpkgs.md",
|
||||
},
|
||||
],
|
||||
|
@ -44,20 +44,6 @@ Overall, I strongly recommend everyone to use Flakes, especially since this book
|
||||
around NixOS and Flakes. However, it's crucial to be prepared for potential problems that
|
||||
may arise due to forthcoming breaking changes.
|
||||
|
||||
## Flakes Tutorials
|
||||
|
||||
I won't go into too much detail here, please refer to the following documents:
|
||||
|
||||
- Nix Flakes's official documentation:
|
||||
- [Nix flakes - Nix Manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake)
|
||||
- [Flakes - nix.dev](https://nix.dev/concepts/flakes)
|
||||
- A series of tutorials by Eelco Dolstra(The creator of Nix) about Flakes:
|
||||
- [Nix Flakes, Part 1: An introduction and tutorial (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-05-25-flakes/)
|
||||
- [Nix Flakes, Part 2: Evaluation caching (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-06-25-eval-cache/)
|
||||
- [Nix Flakes, Part 3: Managing NixOS systems (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-07-31-nixos-flakes/)
|
||||
- Other useful documents:
|
||||
- [Practical Nix Flakes](https://serokell.io/blog/practical-nix-flakes)
|
||||
|
||||
## When Will Flakes Be Stabilized?
|
||||
|
||||
I delved into some details regarding Flakes:
|
||||
|
293
docs/nixos-with-flakes/nixos-flake-and-module-system.md
Normal file
293
docs/nixos-with-flakes/nixos-flake-and-module-system.md
Normal file
@ -0,0 +1,293 @@
|
||||
# The combination ability of Flakes and Nixpkgs module system
|
||||
|
||||
## Nixpkgs Module Structure Explained {#simple-introduction-to-nixpkgs-module-structure}
|
||||
|
||||
> The detailed workings of this module system will be introduced in the following
|
||||
> [Modularizing NixOS Configuration](./modularize-the-configuration.md) section. Here,
|
||||
> we'll just cover some basic knowledge.
|
||||
|
||||
You might be wondering why the `/etc/nixos/configuration.nix` configuration file adheres
|
||||
to the Nixpkgs Module definition and can be referenced directly within the `flake.nix`.
|
||||
|
||||
This is because the Nixpkgs repository contains a significant amount of NixOS
|
||||
implementation source code, primarily written in Nix. To manage and maintain such a large
|
||||
volume of Nix code and to allow users to customize various functions of their NixOS
|
||||
systems, a modular system for Nix code is essential.
|
||||
|
||||
This modular system for Nix code is also implemented within the Nixpkgs repository and is
|
||||
primarily used for modularizing NixOS system configurations. However, it is also widely
|
||||
used in other contexts, such as nix-darwin and home-manager. Since NixOS is built on this
|
||||
modular system, it is only natural that its configuration files, including
|
||||
`/etc/nixos/configuration.nix`, are Nixpkgs Modules.
|
||||
|
||||
Before delving into the subsequent content, it's essential to have a basic understanding
|
||||
of how this module system operates.
|
||||
|
||||
Here's a simplified structure of a Nixpkgs Module:
|
||||
|
||||
```nix
|
||||
{lib, config, options, pkgs, ...}:
|
||||
{
|
||||
# Importing other Modules
|
||||
imports = [
|
||||
# ...
|
||||
./xxx.nix
|
||||
];
|
||||
for.bar.enable = true;
|
||||
# Other option declarations
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
The definition is actually a Nix function, and it has five **automatically generated,
|
||||
automatically injected, and declaration-free parameters** provided by the module system:
|
||||
|
||||
1. `lib`: A built-in function library included with nixpkgs, offering many practical
|
||||
functions for operating Nix expressions.
|
||||
- For more information, see <https://nixos.org/manual/nixpkgs/stable/#id-1.4>.
|
||||
2. `config`: A set of all options' values in the current environment, which will be used
|
||||
extensively in the subsequent section on the module system.
|
||||
3. `options`: A set of all options defined in all Modules in the current environment.
|
||||
4. `pkgs`: A collection containing all nixpkgs packages, along with several related
|
||||
utility functions.
|
||||
- At the beginner stage, you can consider its default value to be
|
||||
`nixpkgs.legacyPackages."${system}"`, and the value of `pkgs` can be customized
|
||||
through the `nixpkgs.pkgs` option.
|
||||
5. `modulesPath`: A parameter available only in NixOS, which is a path pointing to
|
||||
[nixpkgs/nixos/modules](https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/modules).
|
||||
- It is defined in
|
||||
[nixpkgs/nixos/lib/eval-config-minimal.nix#L43](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/lib/eval-config-minimal.nix#L43).
|
||||
- It is typically used to import additional NixOS modules and can be found in most
|
||||
NixOS auto-generated `hardware-configuration.nix` files.
|
||||
|
||||
## Passing Non-default Parameters to Submodules {#pass-non-default-parameters-to-submodules}
|
||||
|
||||
If you need to pass other non-default parameters to submodules, you will need to use some
|
||||
special methods to manually specify these non-default parameters.
|
||||
|
||||
The Nixpkgs module system provides two ways to pass non-default parameters:
|
||||
|
||||
1. The `specialArgs` parameter of the `nixpkgs.lib.nixosSystem` function
|
||||
2. Using the `_module.args` option in any module to pass parameters
|
||||
|
||||
The official documentation for these two parameters is buried deep and is vague and hard
|
||||
to understand. If readers are interested, I will include the links here:
|
||||
|
||||
1. `specialArgs`: There are scattered mentions related to it in the NixOS Manual and the
|
||||
Nixpkgs Manual.
|
||||
- Nixpkgs Manual: [Module System - Nixpkgs]
|
||||
- NixOS Manual:
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]
|
||||
1. `_module.args`:
|
||||
- NixOS Manual:
|
||||
[Appendix A. Configuration Options](https://nixos.org/manual/nixos/stable/options#opt-_module.args)
|
||||
- Source Code: [nixpkgs/nixos-23.11/lib/modules.nix - _module.args]
|
||||
|
||||
In short, `specialArgs` and `_module.args` both require an attribute set as their value,
|
||||
and they serve the same purpose, passing all parameters in the attribute set to all
|
||||
submodules. The difference between them is:
|
||||
|
||||
1. The `_module.args` option can be used in any module to pass parameters to each other,
|
||||
which is more flexible than `specialArgs`, which can only be used in the
|
||||
`nixpkgs.lib.nixosSystem` function.
|
||||
1. `_module.args` is declared within a module, so it must be evaluated after all modules
|
||||
have been evaluated before it can be used. This means that **if you use the parameters
|
||||
passed through `_module.args` in `imports = [ ... ];`, it will result in an
|
||||
`infinite recursion` error**. In this case, you must use `specialArgs` instead.
|
||||
|
||||
The NixOS community generally recommends prioritizing the use of the `_module.args` option
|
||||
and resorting to `specialArgs` only when `_module.args` cannot be used.
|
||||
|
||||
Suppose you want to pass a certain dependency to a submodule for use. You can use the
|
||||
`specialArgs` parameter to pass the `inputs` to all submodules:
|
||||
|
||||
```nix{13}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
# Set all inputs parameters as special arguments for all submodules,
|
||||
# so you can directly use all dependencies in inputs in submodules
|
||||
specialArgs = { inherit inputs; };
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Or you can achieve the same effect using the `_module.args` option:
|
||||
|
||||
```nix{14}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
{
|
||||
# Set all inputs parameters as special arguments for all submodules,
|
||||
# so you can directly use all dependencies in inputs in submodules
|
||||
_module.args = { inherit inputs; };
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Choose one of the two methods above to modify your configuration, and then you can use the
|
||||
`inputs` parameter in `/etc/nixos/configuration.nix`. The module system will automatically
|
||||
match the `inputs` defined in `specialArgs` and inject it into all submodules that require
|
||||
this parameter:
|
||||
|
||||
```nix{3}
|
||||
# Nix will match by name and automatically inject the inputs
|
||||
# from specialArgs/_module.args into the third parameter of this function
|
||||
{ config, pkgs, inputs, ... }:
|
||||
{
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
The next section will demonstrate how to use `specialArgs`/`_module.args` to install
|
||||
system software from other flake sources.
|
||||
|
||||
## Installing System Software from Other Flake Sources {#install-system-packages-from-other-flakes}
|
||||
|
||||
The most common requirement for managing a system is to install software, and we have
|
||||
already seen in the previous section how to install packages from the official nixpkgs
|
||||
repository using `environment.systemPackages`. These packages all come from the official
|
||||
nixpkgs repository.
|
||||
|
||||
Now, we will learn how to install software packages from other flake sources, which is
|
||||
much more flexible than installing directly from nixpkgs. The main use case is to install
|
||||
the latest version of a software that is not yet added or updated in Nixpkgs.
|
||||
|
||||
Taking the Helix editor as an example, here's how to compile and install the master branch
|
||||
of Helix directly.
|
||||
|
||||
First, add the helix input data source to `flake.nix`:
|
||||
|
||||
```nix{6,12,18}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
|
||||
# helix editor, use the master branch
|
||||
helix.url = "github:helix-editor/helix/master";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = { inherit inputs; };
|
||||
modules = [
|
||||
./configuration.nix
|
||||
|
||||
# This module works the same as the `specialArgs` parameter we used above
|
||||
# chose one of the two methods to use
|
||||
# { _module.args = { inherit inputs; };}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Next, you can reference this flake input data source in `configuration.nix`:
|
||||
|
||||
```nix{1,10}
|
||||
{ config, pkgs, inputs, ... }:
|
||||
{
|
||||
# ...
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
wget
|
||||
curl
|
||||
# Here, the helix package is installed from the helix input data source
|
||||
inputs.helix.packages."${pkgs.system}".helix
|
||||
];
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
Make the necessary changes and deploy with `sudo nixos-rebuild switch`. The deployment
|
||||
will take much longer this time because Nix will compile the entire Helix program from
|
||||
source.
|
||||
|
||||
After deployment, you can directly test and verify the installation using the `hx` command
|
||||
in the terminal.
|
||||
|
||||
Additionally, if you just want to try out the latest version of Helix and decide whether
|
||||
to install it on your system later, there is a simpler way to do it in one command (but as
|
||||
mentioned earlier, compiling from source will take a long time):
|
||||
|
||||
```bash
|
||||
nix run github:helix-editor/helix/master
|
||||
```
|
||||
|
||||
We will go into more detail on the usage of `nix run` in the following section
|
||||
[Usage of the New CLI](../other-usage-of-flakes/the-new-cli.md).
|
||||
|
||||
## Leveraging Features from Other Flakes Packages
|
||||
|
||||
In fact, this is the primary functionality of Flakes — a flake can depend on other flakes,
|
||||
allowing it to utilize the features they provide. It's akin to how we incorporate
|
||||
functionalities from other libraries when writing programs in TypeScript, Go, Rust, and
|
||||
other programming languages.
|
||||
|
||||
The example above, using the latest version from the official Helix Flake, illustrates
|
||||
this functionality. More use cases will be discussed later, and here are a few examples
|
||||
referenced for future mention:
|
||||
|
||||
- [Getting Started with Home Manager](./start-using-home-manager.md): This introduces the
|
||||
community's Home-Manager as a dependency, enabling direct utilization of the features
|
||||
provided by this Flake.
|
||||
- [Downgrading or Upgrading Packages](./downgrade-or-upgrade-packages.md): Here, different
|
||||
versions of Nixpkgs are introduced as dependencies, allowing for flexible selection of
|
||||
packages from various versions of Nixpkgs.
|
||||
|
||||
|
||||
## More Flakes Tutorials
|
||||
|
||||
Up to this point, we have learned how to use Flakes to configure NixOS systems.
|
||||
If you have more questions about Flakes or want to learn more in-depth, please refer
|
||||
directly to the following official/semi-official documents:
|
||||
|
||||
- Nix Flakes's official documentation:
|
||||
- [Nix flakes - Nix Manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake)
|
||||
- [Flakes - nix.dev](https://nix.dev/concepts/flakes)
|
||||
- A series of tutorials by Eelco Dolstra(The creator of Nix) about Flakes:
|
||||
- [Nix Flakes, Part 1: An introduction and tutorial (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-05-25-flakes/)
|
||||
- [Nix Flakes, Part 2: Evaluation caching (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-06-25-eval-cache/)
|
||||
- [Nix Flakes, Part 3: Managing NixOS systems (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-07-31-nixos-flakes/)
|
||||
- Other useful documents:
|
||||
- [Practical Nix Flakes](https://serokell.io/blog/practical-nix-flakes)
|
||||
|
||||
|
||||
|
||||
[nix flake - Nix Manual]:
|
||||
https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs
|
||||
[nixpkgs/flake.nix]: https://github.com/NixOS/nixpkgs/tree/nixos-23.11/flake.nix
|
||||
[nixpkgs/nixos/lib/eval-config.nix]:
|
||||
https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/lib/eval-config.nix
|
||||
[Module System - Nixpkgs]:
|
||||
https://github.com/NixOS/nixpkgs/blob/23.11/doc/module-system/module-system.chapter.md
|
||||
[nixpkgs/nixos-23.11/lib/modules.nix - _module.args]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/lib/modules.nix#L122-L184
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/doc/manual/development/option-types.section.md?plain=1#L237-L244
|
||||
|
||||
|
186
docs/nixos-with-flakes/nixos-flake-configuration-explained.md
Normal file
186
docs/nixos-with-flakes/nixos-flake-configuration-explained.md
Normal file
@ -0,0 +1,186 @@
|
||||
# `flake.nix` Configuration Explained {#flake-nix-configuration-explained}
|
||||
|
||||
Above, we created a `flake.nix` file to manage system configurations, but you might still
|
||||
be unclear about its structure. Let's explain the content of this file in detail.
|
||||
|
||||
## 1. Flake Inputs
|
||||
|
||||
First, let's look at the `inputs` attribute. It is an attribute set that defines all the
|
||||
dependencies of this flake. These dependencies will be passed as arguments to the
|
||||
`outputs` function after they are fetched:
|
||||
|
||||
```nix{2-5,7}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS official package source, using the nixos-23.11 branch here
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# Omitting previous configurations......
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Dependencies in `inputs` has many types and definitions. It can be another flake, a
|
||||
regular Git repository, or a local path. The section
|
||||
[Other Usage of Flakes - Flake Inputs](../other-usage-of-flakes/inputs.md) describes
|
||||
common types of dependencies and their definitions in detail.
|
||||
|
||||
Here we only define a dependency named `nixpkgs`, which is the most common way to
|
||||
reference in a flake, i.e., `github:owner/name/reference`. The `reference` here can be a
|
||||
branch name, commit-id, or tag.
|
||||
|
||||
After `nixpkgs` is defined in `inputs`, you can use it in the parameters of the subsequent
|
||||
`outputs` function, which is exactly what our example does.
|
||||
|
||||
## 2. Flake Outputs
|
||||
|
||||
Now let's look at `outputs`. It is a function that takes the dependencies from `inputs` as
|
||||
its parameters, and its return value is an attribute set, which represents the build
|
||||
results of the flake:
|
||||
|
||||
```nix{11-19}
|
||||
{
|
||||
description = "A simple NixOS flake";
|
||||
|
||||
inputs = {
|
||||
# NixOS official package source, here using the nixos-23.11 branch
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# The host with the hostname `my-nixos` will use this configuration
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Flakes can have various purposes and can have different types of outputs. The section
|
||||
[Flake Outputs](../other-usage-of-flakes/outputs.md) provides a more detailed
|
||||
introduction. Here, we are only using the `nixosConfigurations` type of outputs, which is
|
||||
used to configure NixOS systems.
|
||||
|
||||
When we run the `sudo nixos-rebuild switch` command, it looks for the
|
||||
`nixosConfigurations.my-nixos` attribute (where `my-nixos` will be the hostname of your
|
||||
current system) in the attribute set returned by the `outputs` function of
|
||||
`/etc/nixos/flake.nix` and uses the definition there to configure your NixOS system.
|
||||
|
||||
Actually, we can also customize the location of the flake and the name of the NixOS
|
||||
configuration instead of using the defaults. This can be done by adding the `--flake`
|
||||
parameter to the `nixos-rebuild` command. Here's an example:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake /path/to/your/flake#your-hostname
|
||||
```
|
||||
|
||||
A brief explanation of the `--flake /path/to/your/flake#your-hostname` parameter:
|
||||
|
||||
1. `/path/to/your/flake` is the location of the target flake. The default path is
|
||||
`/etc/nixos/`.
|
||||
2. `#` is a separator, and `your-hostname` is the name of the NixOS configuration.
|
||||
`nixos-rebuild` will default to using the hostname of your current system as the
|
||||
configuration name to look for.
|
||||
|
||||
You can even directly reference a remote GitHub repository as your flake source, for
|
||||
example:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake github:owner/repo#your-hostname
|
||||
```
|
||||
|
||||
## 3. The Special Parameter `self` of the `outputs` Function {#special-parameter-self-of-outputs-function}
|
||||
|
||||
Although we have not mentioned it before, all the example code in the previous sections
|
||||
has one more special parameter in the `outputs` function, and we will briefly introduce
|
||||
its purpose here.
|
||||
|
||||
The description of it in the [nix flake - Nix Manual] is:
|
||||
|
||||
> The special input named `self` refers to the outputs and source tree of this flake.
|
||||
|
||||
This means that `self` is the return value of the current flake's `outputs` function and
|
||||
also the path to the current flake's source code folder (source tree).
|
||||
|
||||
We are not using the `self` parameter here, but in some more complex examples (or
|
||||
configurations you may find online) later, you will see the usage of `self`.
|
||||
|
||||
> Note: You might come across some code where people use `self.outputs` to reference the
|
||||
> outputs of the current flake, which is indeed possible. However, the Nix Manual does not
|
||||
> provide any explanation for this, and it is considered an internal implementation detail
|
||||
> of flakes. It is not recommended to use this in your own code!
|
||||
|
||||
## 4. Simple Introduction to `nixpkgs.lib.nixosSystem` Function {#simple-introduction-to-nixpkgs-lib-nixos-system}
|
||||
|
||||
**A Flake can depend on other Flakes to utilize the features they provide.**
|
||||
|
||||
By default, a flake searches for a `flake.nix` file in the root directory of each of its
|
||||
dependencies (i.e., each item in `inputs`) and lazily evaluates their `outputs` functions.
|
||||
It then passes the attribute set returned by these functions as arguments to its own
|
||||
`outputs` function, enabling us to use the features provided by the other flakes within
|
||||
our current flake.
|
||||
|
||||
More precisely, the evaluation of the `outputs` function for each dependency is lazy. This
|
||||
means that a flake's `outputs` function is only evaluated when it is actually used,
|
||||
thereby avoiding unnecessary calculations and improving efficiency.
|
||||
|
||||
The description above may be a bit confusing, so let's take a look at the process with the
|
||||
`flake.nix` example used in this section. Our `flake.nix` declares the `inputs.nixpkgs`
|
||||
dependency, so that [nixpkgs/flake.nix] will be evaluated when we run the
|
||||
`sudo nixos-rebuild switch` command.
|
||||
|
||||
From the source code of the Nixpkgs repository, we can see that its flake outputs
|
||||
definition includes the `lib` attribute, and in our example, we use the `lib` attribute's
|
||||
`nixosSystem` function to configure our NixOS system:
|
||||
|
||||
```nix{8-13}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS official package source, here using the nixos-23.11 branch
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The attribute set following `nixpkgs.lib.nixosSystem` is the function's parameter. We have
|
||||
only set two parameters here:
|
||||
|
||||
1. `system`: This is straightforward, it's the system architecture parameter.
|
||||
2. `modules`: This is a list of modules, where the actual NixOS system configuration is
|
||||
defined. The `/etc/nixos/configuration.nix` configuration file itself is a Nixpkgs
|
||||
Module, so it can be directly added to the `modules` list for use.
|
||||
|
||||
Understanding these basics is sufficient for beginners. Exploring the
|
||||
`nixpkgs.lib.nixosSystem` function in detail requires a grasp of the Nixpkgs module
|
||||
system. Readers who have completed the
|
||||
[Modularizing NixOS Configuration](./modularize-the-configuration.md) section can return
|
||||
to [nixpkgs/flake.nix] to find the definition of `nixpkgs.lib.nixosSystem`, trace its
|
||||
source code, and study its implementation.
|
||||
|
||||
[nix flake - Nix Manual]:
|
||||
https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs
|
||||
[nixpkgs/flake.nix]: https://github.com/NixOS/nixpkgs/tree/nixos-23.11/flake.nix
|
||||
[nixpkgs/nixos/lib/eval-config.nix]:
|
||||
https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/lib/eval-config.nix
|
||||
[Module System - Nixpkgs]:
|
||||
https://github.com/NixOS/nixpkgs/blob/23.11/doc/module-system/module-system.chapter.md
|
||||
[nixpkgs/nixos-23.11/lib/modules.nix - _module.args]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/lib/modules.nix#L122-L184
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/doc/manual/development/option-types.section.md?plain=1#L237-L244
|
||||
|
||||
|
@ -1,13 +1,18 @@
|
||||
# Enabling NixOS with Flakes
|
||||
|
||||
## Enabling Flakes Support for NixOS {#enable-nix-flakes}
|
||||
|
||||
Compared to the default configuration method currently used in NixOS, Flakes offers better
|
||||
reproducibility. Its clear package structure definition inherently supports dependencies
|
||||
on other Git repositories, facilitating code sharing. Therefore, this book suggests using
|
||||
Flakes to manage system configurations. Currently, Flakes is still an experimental feature
|
||||
and not enabled by default. We need to manually modify the `/etc/nixos/configuration.nix`
|
||||
file to enable the Flakes feature and the accompanying new nix command-line tool:
|
||||
Flakes to manage system configurations.
|
||||
|
||||
This section describes how to use Flakes to manage NixOS system configuration, and **you
|
||||
don't need to know anything about Flakes in advance**.
|
||||
|
||||
## Enabling Flakes Support for NixOS {#enable-nix-flakes}
|
||||
|
||||
Currently, Flakes is still an experimental feature and not enabled by default. We need to
|
||||
manually modify the `/etc/nixos/configuration.nix` file to enable the Flakes feature and
|
||||
the accompanying new nix command-line tool:
|
||||
|
||||
```nix{12,16}
|
||||
{ config, pkgs, ... }:
|
||||
@ -115,10 +120,17 @@ Currently, our flake includes these files:
|
||||
- `/etc/nixos/hardware-configuration.nix`: This is the system hardware configuration file,
|
||||
generated by NixOS, which describes the system's hardware information.
|
||||
|
||||
Up to this point, `/etc/nixos/flake.nix` has merely been a thin wrapper around
|
||||
## Cconclusion
|
||||
|
||||
Up to this point, we have merely added a very simple configuration file,
|
||||
`/etc/nixos/flake.nix`, which has merely been a thin wrapper around
|
||||
`/etc/nixos/configuration.nix`, offering no new functionality and introducing no
|
||||
disruptive changes. In the content of the book that follows, we will gradually see the
|
||||
benefits that such a wrapper brings.
|
||||
disruptive changes.
|
||||
|
||||
In the content of the book that follows, we will learn about the structure and
|
||||
functionality of `flake.nix` and gradually see the benefits that such a wrapper can
|
||||
bring.
|
||||
|
||||
|
||||
> Note: The configuration management method described in this book is NOT "Everything in a
|
||||
> single file". It is recommended to categorize configuration content into different nix
|
||||
@ -132,438 +144,6 @@ benefits that such a wrapper brings.
|
||||
> [Other Useful Tips - Managing NixOS Configuration with Git](./other-useful-tips.md) will
|
||||
> introduce several best practices for managing NixOS configuration with Git.
|
||||
|
||||
## `flake.nix` Configuration Explained {#flake-nix-configuration-explained}
|
||||
|
||||
Above, we created a `flake.nix` file to manage system configurations, but you might still
|
||||
be unclear about its structure. Let's explain the content of this file in detail.
|
||||
|
||||
### 1. Flake Inputs
|
||||
|
||||
First, let's look at the `inputs` attribute. It is an attribute set that defines all the
|
||||
dependencies of this flake. These dependencies will be passed as arguments to the
|
||||
`outputs` function after they are fetched:
|
||||
|
||||
```nix{2-5,7}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS official package source, using the nixos-23.11 branch here
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# Omitting previous configurations......
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Dependencies in `inputs` has many types and definitions. It can be another flake, a
|
||||
regular Git repository, or a local path. The section
|
||||
[Other Usage of Flakes - Flake Inputs](../other-usage-of-flakes/inputs.md) describes
|
||||
common types of dependencies and their definitions in detail.
|
||||
|
||||
Here we only define a dependency named `nixpkgs`, which is the most common way to
|
||||
reference in a flake, i.e., `github:owner/name/reference`. The `reference` here can be a
|
||||
branch name, commit-id, or tag.
|
||||
|
||||
After `nixpkgs` is defined in `inputs`, you can use it in the parameters of the subsequent
|
||||
`outputs` function, which is exactly what our example does.
|
||||
|
||||
### 2. Flake Outputs
|
||||
|
||||
Now let's look at `outputs`. It is a function that takes the dependencies from `inputs` as
|
||||
its parameters, and its return value is an attribute set, which represents the build
|
||||
results of the flake:
|
||||
|
||||
```nix{11-19}
|
||||
{
|
||||
description = "A simple NixOS flake";
|
||||
|
||||
inputs = {
|
||||
# NixOS official package source, here using the nixos-23.11 branch
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# The host with the hostname `my-nixos` will use this configuration
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Flakes can have various purposes and can have different types of outputs. The section
|
||||
[Flake Outputs](../other-usage-of-flakes/outputs.md) provides a more detailed
|
||||
introduction. Here, we are only using the `nixosConfigurations` type of outputs, which is
|
||||
used to configure NixOS systems.
|
||||
|
||||
When we run the `sudo nixos-rebuild switch` command, it looks for the
|
||||
`nixosConfigurations.my-nixos` attribute (where `my-nixos` will be the hostname of your
|
||||
current system) in the attribute set returned by the `outputs` function of
|
||||
`/etc/nixos/flake.nix` and uses the definition there to configure your NixOS system.
|
||||
|
||||
Actually, we can also customize the location of the flake and the name of the NixOS
|
||||
configuration instead of using the defaults. This can be done by adding the `--flake`
|
||||
parameter to the `nixos-rebuild` command. Here's an example:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake /path/to/your/flake#your-hostname
|
||||
```
|
||||
|
||||
A brief explanation of the `--flake /path/to/your/flake#your-hostname` parameter:
|
||||
|
||||
1. `/path/to/your/flake` is the location of the target flake. The default path is
|
||||
`/etc/nixos/`.
|
||||
2. `#` is a separator, and `your-hostname` is the name of the NixOS configuration.
|
||||
`nixos-rebuild` will default to using the hostname of your current system as the
|
||||
configuration name to look for.
|
||||
|
||||
You can even directly reference a remote GitHub repository as your flake source, for
|
||||
example:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake github:owner/repo#your-hostname
|
||||
```
|
||||
|
||||
### 3. The Special Parameter `self` of the `outputs` Function {#special-parameter-self-of-outputs-function}
|
||||
|
||||
Although we have not mentioned it before, all the example code in the previous sections
|
||||
has one more special parameter in the `outputs` function, and we will briefly introduce
|
||||
its purpose here.
|
||||
|
||||
The description of it in the [nix flake - Nix Manual] is:
|
||||
|
||||
> The special input named `self` refers to the outputs and source tree of this flake.
|
||||
|
||||
This means that `self` is the return value of the current flake's `outputs` function and
|
||||
also the path to the current flake's source code folder (source tree).
|
||||
|
||||
We are not using the `self` parameter here, but in some more complex examples (or
|
||||
configurations you may find online) later, you will see the usage of `self`.
|
||||
|
||||
> Note: You might come across some code where people use `self.outputs` to reference the
|
||||
> outputs of the current flake, which is indeed possible. However, the Nix Manual does not
|
||||
> provide any explanation for this, and it is considered an internal implementation detail
|
||||
> of flakes. It is not recommended to use this in your own code!
|
||||
|
||||
### 4. Simple Introduction to `nixpkgs.lib.nixosSystem` Function {#simple-introduction-to-nixpkgs-lib-nixos-system}
|
||||
|
||||
**A Flake can depend on other Flakes to utilize the features they provide.**
|
||||
|
||||
By default, a flake searches for a `flake.nix` file in the root directory of each of its
|
||||
dependencies (i.e., each item in `inputs`) and lazily evaluates their `outputs` functions.
|
||||
It then passes the attribute set returned by these functions as arguments to its own
|
||||
`outputs` function, enabling us to use the features provided by the other flakes within
|
||||
our current flake.
|
||||
|
||||
More precisely, the evaluation of the `outputs` function for each dependency is lazy. This
|
||||
means that a flake's `outputs` function is only evaluated when it is actually used,
|
||||
thereby avoiding unnecessary calculations and improving efficiency.
|
||||
|
||||
The description above may be a bit confusing, so let's take a look at the process with the
|
||||
`flake.nix` example used in this section. Our `flake.nix` declares the `inputs.nixpkgs`
|
||||
dependency, so that [nixpkgs/flake.nix] will be evaluated when we run the
|
||||
`sudo nixos-rebuild switch` command.
|
||||
|
||||
From the source code of the Nixpkgs repository, we can see that its flake outputs
|
||||
definition includes the `lib` attribute, and in our example, we use the `lib` attribute's
|
||||
`nixosSystem` function to configure our NixOS system:
|
||||
|
||||
```nix{8-13}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS official package source, here using the nixos-23.11 branch
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The attribute set following `nixpkgs.lib.nixosSystem` is the function's parameter. We have
|
||||
only set two parameters here:
|
||||
|
||||
1. `system`: This is straightforward, it's the system architecture parameter.
|
||||
2. `modules`: This is a list of modules, where the actual NixOS system configuration is
|
||||
defined. The `/etc/nixos/configuration.nix` configuration file itself is a Nixpkgs
|
||||
Module, so it can be directly added to the `modules` list for use.
|
||||
|
||||
Understanding these basics is sufficient for beginners. Exploring the
|
||||
`nixpkgs.lib.nixosSystem` function in detail requires a grasp of the Nixpkgs module
|
||||
system. Readers who have completed the
|
||||
[Modularizing NixOS Configuration](./modularize-the-configuration.md) section can return
|
||||
to [nixpkgs/flake.nix] to find the definition of `nixpkgs.lib.nixosSystem`, trace its
|
||||
source code, and study its implementation.
|
||||
|
||||
## Nixpkgs Module Structure Explained {#simple-introduction-to-nixpkgs-module-structure}
|
||||
|
||||
> The detailed workings of this module system will be introduced in the following
|
||||
> [Modularizing NixOS Configuration](./modularize-the-configuration.md) section. Here,
|
||||
> we'll just cover some basic knowledge.
|
||||
|
||||
You might be wondering why the `/etc/nixos/configuration.nix` configuration file adheres
|
||||
to the Nixpkgs Module definition and can be referenced directly within the `flake.nix`.
|
||||
|
||||
This is because the Nixpkgs repository contains a significant amount of NixOS
|
||||
implementation source code, primarily written in Nix. To manage and maintain such a large
|
||||
volume of Nix code and to allow users to customize various functions of their NixOS
|
||||
systems, a modular system for Nix code is essential.
|
||||
|
||||
This modular system for Nix code is also implemented within the Nixpkgs repository and is
|
||||
primarily used for modularizing NixOS system configurations. However, it is also widely
|
||||
used in other contexts, such as nix-darwin and home-manager. Since NixOS is built on this
|
||||
modular system, it is only natural that its configuration files, including
|
||||
`/etc/nixos/configuration.nix`, are Nixpkgs Modules.
|
||||
|
||||
Before delving into the subsequent content, it's essential to have a basic understanding
|
||||
of how this module system operates.
|
||||
|
||||
Here's a simplified structure of a Nixpkgs Module:
|
||||
|
||||
```nix
|
||||
{lib, config, options, pkgs, ...}:
|
||||
{
|
||||
# Importing other Modules
|
||||
imports = [
|
||||
# ...
|
||||
./xxx.nix
|
||||
];
|
||||
for.bar.enable = true;
|
||||
# Other option declarations
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
The definition is actually a Nix function, and it has five **automatically generated,
|
||||
automatically injected, and declaration-free parameters** provided by the module system:
|
||||
|
||||
1. `lib`: A built-in function library included with nixpkgs, offering many practical
|
||||
functions for operating Nix expressions.
|
||||
- For more information, see <https://nixos.org/manual/nixpkgs/stable/#id-1.4>.
|
||||
2. `config`: A set of all options' values in the current environment, which will be used
|
||||
extensively in the subsequent section on the module system.
|
||||
3. `options`: A set of all options defined in all Modules in the current environment.
|
||||
4. `pkgs`: A collection containing all nixpkgs packages, along with several related
|
||||
utility functions.
|
||||
- At the beginner stage, you can consider its default value to be
|
||||
`nixpkgs.legacyPackages."${system}"`, and the value of `pkgs` can be customized
|
||||
through the `nixpkgs.pkgs` option.
|
||||
5. `modulesPath`: A parameter available only in NixOS, which is a path pointing to
|
||||
[nixpkgs/nixos/modules](https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/modules).
|
||||
- It is defined in
|
||||
[nixpkgs/nixos/lib/eval-config-minimal.nix#L43](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/lib/eval-config-minimal.nix#L43).
|
||||
- It is typically used to import additional NixOS modules and can be found in most
|
||||
NixOS auto-generated `hardware-configuration.nix` files.
|
||||
|
||||
## Passing Non-default Parameters to Submodules {#pass-non-default-parameters-to-submodules}
|
||||
|
||||
If you need to pass other non-default parameters to submodules, you will need to use some
|
||||
special methods to manually specify these non-default parameters.
|
||||
|
||||
The Nixpkgs module system provides two ways to pass non-default parameters:
|
||||
|
||||
1. The `specialArgs` parameter of the `nixpkgs.lib.nixosSystem` function
|
||||
2. Using the `_module.args` option in any module to pass parameters
|
||||
|
||||
The official documentation for these two parameters is buried deep and is vague and hard
|
||||
to understand. If readers are interested, I will include the links here:
|
||||
|
||||
1. `specialArgs`: There are scattered mentions related to it in the NixOS Manual and the
|
||||
Nixpkgs Manual.
|
||||
- Nixpkgs Manual: [Module System - Nixpkgs]
|
||||
- NixOS Manual:
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]
|
||||
1. `_module.args`:
|
||||
- NixOS Manual:
|
||||
[Appendix A. Configuration Options](https://nixos.org/manual/nixos/stable/options#opt-_module.args)
|
||||
- Source Code: [nixpkgs/nixos-23.11/lib/modules.nix - _module.args]
|
||||
|
||||
In short, `specialArgs` and `_module.args` both require an attribute set as their value,
|
||||
and they serve the same purpose, passing all parameters in the attribute set to all
|
||||
submodules. The difference between them is:
|
||||
|
||||
1. The `_module.args` option can be used in any module to pass parameters to each other,
|
||||
which is more flexible than `specialArgs`, which can only be used in the
|
||||
`nixpkgs.lib.nixosSystem` function.
|
||||
1. `_module.args` is declared within a module, so it must be evaluated after all modules
|
||||
have been evaluated before it can be used. This means that **if you use the parameters
|
||||
passed through `_module.args` in `imports = [ ... ];`, it will result in an
|
||||
`infinite recursion` error**. In this case, you must use `specialArgs` instead.
|
||||
|
||||
The NixOS community generally recommends prioritizing the use of the `_module.args` option
|
||||
and resorting to `specialArgs` only when `_module.args` cannot be used.
|
||||
|
||||
Suppose you want to pass a certain dependency to a submodule for use. You can use the
|
||||
`specialArgs` parameter to pass the `inputs` to all submodules:
|
||||
|
||||
```nix{13}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
# Set all inputs parameters as special arguments for all submodules,
|
||||
# so you can directly use all dependencies in inputs in submodules
|
||||
specialArgs = { inherit inputs; };
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Or you can achieve the same effect using the `_module.args` option:
|
||||
|
||||
```nix{14}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
{
|
||||
# Set all inputs parameters as special arguments for all submodules,
|
||||
# so you can directly use all dependencies in inputs in submodules
|
||||
_module.args = { inherit inputs; };
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Choose one of the two methods above to modify your configuration, and then you can use the
|
||||
`inputs` parameter in `/etc/nixos/configuration.nix`. The module system will automatically
|
||||
match the `inputs` defined in `specialArgs` and inject it into all submodules that require
|
||||
this parameter:
|
||||
|
||||
```nix{3}
|
||||
# Nix will match by name and automatically inject the inputs
|
||||
# from specialArgs/_module.args into the third parameter of this function
|
||||
{ config, pkgs, inputs, ... }:
|
||||
{
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
The next section will demonstrate how to use `specialArgs`/`_module.args` to install
|
||||
system software from other flake sources.
|
||||
|
||||
## Installing System Software from Other Flake Sources {#install-system-packages-from-other-flakes}
|
||||
|
||||
The most common requirement for managing a system is to install software, and we have
|
||||
already seen in the previous section how to install packages from the official nixpkgs
|
||||
repository using `environment.systemPackages`. These packages all come from the official
|
||||
nixpkgs repository.
|
||||
|
||||
Now, we will learn how to install software packages from other flake sources, which is
|
||||
much more flexible than installing directly from nixpkgs. The main use case is to install
|
||||
the latest version of a software that is not yet added or updated in Nixpkgs.
|
||||
|
||||
Taking the Helix editor as an example, here's how to compile and install the master branch
|
||||
of Helix directly.
|
||||
|
||||
First, add the helix input data source to `flake.nix`:
|
||||
|
||||
```nix{6,12,18}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
|
||||
# helix editor, use the master branch
|
||||
helix.url = "github:helix-editor/helix/master";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = { inherit inputs; };
|
||||
modules = [
|
||||
./configuration.nix
|
||||
|
||||
# This module works the same as the `specialArgs` parameter we used above
|
||||
# chose one of the two methods to use
|
||||
# { _module.args = { inherit inputs; };}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Next, you can reference this flake input data source in `configuration.nix`:
|
||||
|
||||
```nix{1,10}
|
||||
{ config, pkgs, inputs, ... }:
|
||||
{
|
||||
# ...
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
wget
|
||||
curl
|
||||
# Here, the helix package is installed from the helix input data source
|
||||
inputs.helix.packages."${pkgs.system}".helix
|
||||
];
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
Make the necessary changes and deploy with `sudo nixos-rebuild switch`. The deployment
|
||||
will take much longer this time because Nix will compile the entire Helix program from
|
||||
source.
|
||||
|
||||
After deployment, you can directly test and verify the installation using the `hx` command
|
||||
in the terminal.
|
||||
|
||||
Additionally, if you just want to try out the latest version of Helix and decide whether
|
||||
to install it on your system later, there is a simpler way to do it in one command (but as
|
||||
mentioned earlier, compiling from source will take a long time):
|
||||
|
||||
```bash
|
||||
nix run github:helix-editor/helix/master
|
||||
```
|
||||
|
||||
We will go into more detail on the usage of `nix run` in the following section
|
||||
[Usage of the New CLI](../other-usage-of-flakes/the-new-cli.md).
|
||||
|
||||
## Leveraging Features from Other Flakes Packages
|
||||
|
||||
In fact, this is the primary functionality of Flakes — a flake can depend on other flakes,
|
||||
allowing it to utilize the features they provide. It's akin to how we incorporate
|
||||
functionalities from other libraries when writing programs in TypeScript, Go, Rust, and
|
||||
other programming languages.
|
||||
|
||||
The example above, using the latest version from the official Helix Flake, illustrates
|
||||
this functionality. More use cases will be discussed later, and here are a few examples
|
||||
referenced for future mention:
|
||||
|
||||
- [Getting Started with Home Manager](./start-using-home-manager.md): This introduces the
|
||||
community's Home-Manager as a dependency, enabling direct utilization of the features
|
||||
provided by this Flake.
|
||||
- [Downgrading or Upgrading Packages](./downgrade-or-upgrade-packages.md): Here, different
|
||||
versions of Nixpkgs are introduced as dependencies, allowing for flexible selection of
|
||||
packages from various versions of Nixpkgs.
|
||||
|
||||
[nix flake - Nix Manual]:
|
||||
https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs
|
||||
[nixpkgs/flake.nix]: https://github.com/NixOS/nixpkgs/tree/nixos-23.11/flake.nix
|
||||
|
@ -35,20 +35,6 @@ Flakes[^3],因此我们可以相当确定 Flakes 不会被废弃。
|
||||
总的来说,我仍然推荐大家使用 Flakes,毕竟这本书本身也是围绕 NixOS 与 Flakes 编写的,但是也
|
||||
要做好准备——未来可能需要解决一些不兼容变更带来的问题。
|
||||
|
||||
## Flakes 入门
|
||||
|
||||
限于个人精力,我不会在本书中详细介绍 Flakes 的使用,
|
||||
请直接参考如下官方/半官方的文档。
|
||||
|
||||
- Nix Flakes 的官方文档:
|
||||
- [Nix flakes - Nix Manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake)
|
||||
- [Flakes - nix.dev](https://nix.dev/concepts/flakes)
|
||||
- Eelco Dolstra (Nix 的创造者)的一系列关于 Flakes 的文章:
|
||||
- [Nix Flakes, Part 1: An introduction and tutorial (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-05-25-flakes/)
|
||||
- [Nix Flakes, Part 2: Evaluation caching (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-06-25-eval-cache/)
|
||||
- [Nix Flakes, Part 3: Managing NixOS systems (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-07-31-nixos-flakes/)
|
||||
- 其他可能有用的文档:
|
||||
- [Practical Nix Flakes](https://serokell.io/blog/practical-nix-flakes)
|
||||
|
||||
## Flakes 何时会成为稳定特性? {#when-will-flakes-stablized}
|
||||
|
||||
|
269
docs/zh/nixos-with-flakes/nixos-flake-and-module-system.md
Normal file
269
docs/zh/nixos-with-flakes/nixos-flake-and-module-system.md
Normal file
@ -0,0 +1,269 @@
|
||||
# Flakes 的组合能力与 Nixpkgs Module 系统
|
||||
|
||||
## Nixpkgs Module 结构的简单介绍 {#simple-introduction-to-nixpkgs-module-structure}
|
||||
|
||||
> 在后面的 [模块化 NixOS 配置](./modularize-the-configuration.md) 一节中会详细介绍这套模块
|
||||
> 系统的工作方式,这里只介绍些基础知识。
|
||||
|
||||
为什么 `/etc/nixos/configuration.nix` 这个配置文件会符合 Nixpkgs Module 定义,从而能直接在
|
||||
`flake.nix` 中引用它呢?可能会有读者觉得这有点出乎意料。
|
||||
|
||||
这实际是因为 Nixpkgs 中包含了大量 NixOS 的实现源码,这些源码大都使用 Nix 语言编写。为了编
|
||||
写维护如此多的 Nix 代码,并且使用户能灵活地自定义其 NixOS 系统的各项功能,就必须要有一套
|
||||
Nix 代码的模块化系统。
|
||||
|
||||
这套 Nix 代码的模块系统的实现也同样在 Nixpkgs 仓库中,它主要被用于 NixOS 系统配置的模块
|
||||
化,但也有其他的应用,比如 nix-darwin 跟 home-manager 都大量使用了这套模块系统。
|
||||
|
||||
既然 NixOS 是基于这套模块系统构建的,那它的配置文件(包括 `/etc/nixos/configuration.nix`)
|
||||
是一个Nixpkgs Module,也就显得非常自然了。
|
||||
|
||||
在学习后面的内容之前,我们需要先简单了解下这套模块系统的工作方式。
|
||||
|
||||
一个简化的 Nixpkgs Module 结构如下:
|
||||
|
||||
```nix
|
||||
{lib, config, options, pkgs, ...}:
|
||||
{
|
||||
# 导入其他 Modules
|
||||
imports = [
|
||||
# ......
|
||||
# ./xxx.nix
|
||||
];
|
||||
|
||||
for.bar.enable = true;
|
||||
# other options declarations
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
可以看到它的定义实际是一个 Nix 函数,该函数有 5 个**由模块系统自动生成、自动注入、无需额外
|
||||
声明的参数**:
|
||||
|
||||
1. `lib`: **nixpkgs 自带的函数库,提供了许多操作 Nix 表达式的实用函数**
|
||||
- 详见 <https://nixos.org/manual/nixpkgs/stable/#id-1.4>
|
||||
2. `config`: 包含了当前环境中所有 option 的值,在后面学习模块系统时会大量使用它
|
||||
3. `options`: 当前环境中所有 Modules 中定义的所有 options 的集合
|
||||
4. `pkgs`: **一个包含所有 nixpkgs 包的集合,它也提供了许多相关的工具函数**
|
||||
- 入门阶段可以认为它的默认值为 `nixpkgs.legacyPackages."${system}"`,可通过
|
||||
`nixpkgs.pkgs` 这个 option 来自定义 `pkgs` 的值
|
||||
5. `modulesPath`: 一个只在 NixOS 中可用的参数,是一个 Path,指向
|
||||
[nixpkgs/nixos/modules](https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/modules)
|
||||
- 它在
|
||||
[nixpkgs/nixos/lib/eval-config-minimal.nix#L43](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/lib/eval-config-minimal.nix#L43)
|
||||
中被定义
|
||||
- 通常被用于导入一些额外的 NixOS 模块,NixOS 自动生成的 `hardware-configuration.nix` 中
|
||||
基本都能看到它
|
||||
|
||||
## 传递非默认参数到模块系统中 {#pass-non-default-parameters-to-submodules}
|
||||
|
||||
而如果你需要将其他非默认参数传递到子模块,就需要使用一些特殊手段手动指定这些非默认参数。
|
||||
|
||||
Nixpkgs 的模块系统提供了两种方式来传递非默认参数:
|
||||
|
||||
1. `nixpkgs.lib.nixosSystem` 函数的 `specialArgs` 参数
|
||||
1. 在任一 Module 中使用 `_module.args` 这个 option 来传递参数
|
||||
|
||||
这两个参数的官方文档藏得很深,而且语焉不详、晦涩难懂。读者感兴趣的话我把链接放在这里:
|
||||
|
||||
1. `specialArgs`: NixOS Manual 跟 Nixpkgs Manual 中分别有与它有关的只言片语
|
||||
- Nixpkgs Manual: [Module System - Nixpkgs]
|
||||
- NixOS Manual:
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]
|
||||
1. `_module.args`:
|
||||
- NixOS Manual:
|
||||
[Appendix A. Configuration Options](https://nixos.org/manual/nixos/stable/options#opt-_module.args)
|
||||
- Source Code: [nixpkgs/nixos-23.11/lib/modules.nix - _module.args]
|
||||
|
||||
总之,`specialArgs` 与 `_module.args` 需要的值都是一个 attribute set,它们的功能也相同,都
|
||||
是将其 attribute set 中的所有参数传递到所有子模块中。这两者的区别在于:
|
||||
|
||||
1. 在任何 Module 中都能使用 `_module.args` 这个 option,通过它互相传递参数,这要比只能在
|
||||
`nixpkgs.lib.nixosSystem` 函数中使用的 `specialArgs` 更灵活。
|
||||
1. `_module.args` 是在 Module 中声明使用的,因此必须在所有 Modules 都已经被求值后,才能使
|
||||
用它。这导致**如果你在 `imports = [ ... ];` 中使用 `_module.args` 传递的参数,会报错
|
||||
`infinite recursion`,这种场景下你必须改用 `specialArgs` 才行**。
|
||||
|
||||
NixOS 社区比较推荐优先使用 `_module.args` 这个 options,仅在无法使用 `_module.args` 时才改
|
||||
用 `specialArgs`。
|
||||
|
||||
假设你想将某个依赖项传递到子模块中使用,可以使用 `specialArgs` 参数将 `inputs` 传递到所有
|
||||
子模块中:
|
||||
|
||||
```nix{13}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
# 将所有 inputs 参数设为所有子模块的特殊参数,
|
||||
# 这样就能直接在子模块中使用 inputs 中的所有依赖项了
|
||||
specialArgs = { inherit inputs;};
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
或者使用 `_module.args` 这个 option 也能达成同样的效果:
|
||||
|
||||
```nix{15}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
{
|
||||
# 将所有 inputs 参数设为所有子模块的特殊参数,
|
||||
# 这样就能直接在子模块中使用 inputs 中的所有依赖项了
|
||||
_module.args = { inherit inputs; };
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
选择上述两种方式之一修改你的配置,然后在 `/etc/nixos/configuration.nix` 中就可以使用
|
||||
`inputs` 这个参数了,模块系统会自动匹配到 `specialArgs` 中定义的 `inputs`,并将其注入到所
|
||||
有需要该参数的子模块中:
|
||||
|
||||
```nix{3}
|
||||
# Nix 会通过名称匹配,
|
||||
# 自动将 specialArgs/_module.args 中的 inputs 注入到此函数的第三个参数
|
||||
{ config, pkgs, inputs, ... }:
|
||||
|
||||
# 然后我们就能在这下面使用 inputs 这个参数了
|
||||
{
|
||||
# ......
|
||||
}
|
||||
```
|
||||
|
||||
下一节将演示如何使用 `specialArgs`/`_module.args` 来从其他 flake 来源安装系统软件。
|
||||
|
||||
## 从其他 flakes 安装系统软件 {#install-system-packages-from-other-flakes}
|
||||
|
||||
管系统最常见的需求就是装软件,我们在上一节已经见识过如何通过 `environment.systemPackages`
|
||||
来安装 `pkgs` 中的包,这些包都来自官方的 nixpkgs 仓库。
|
||||
|
||||
现在我们学习下如何安装其他 flake 来源的软件包,这比直接从 nixpkgs 安装要灵活很多,最主要的
|
||||
用途是安装 Nixpkgs 中还未添加或未更新的某软件的最新版本。
|
||||
|
||||
以 [helix](https://github.com/helix-editor/helix) 编辑器为例,这里演示下如何直接编译安装
|
||||
helix 的 master 分支。
|
||||
|
||||
首先在 `flake.nix` 中添加 helix 这个 inputs 数据源:
|
||||
|
||||
```nix{6,12,18}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
|
||||
# helix editor, use the master branch
|
||||
helix.url = "github:helix-editor/helix/master";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = { inherit inputs;};
|
||||
modules = [
|
||||
./configuration.nix
|
||||
|
||||
# 如下 Module 与前面的 `specialArgs` 参数功能完全一致
|
||||
# 选择其中一种即可
|
||||
# { _module.args = { inherit inputs; };}
|
||||
];
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
接下来在 `configuration.nix` 中就能引用这个 flake input 数据源了:
|
||||
|
||||
```nix{1,10}
|
||||
{ config, pkgs, inputs, ... }:
|
||||
{
|
||||
# 省略无关配置......
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
wget
|
||||
curl
|
||||
# 这里从 helix 这个 inputs 数据源安装了 helix 程序
|
||||
inputs.helix.packages."${pkgs.system}".helix
|
||||
];
|
||||
# 省略其他配置......
|
||||
}
|
||||
```
|
||||
|
||||
改好后再 `sudo nixos-rebuild switch` 部署,就能安装好 Helix 程序了。这次部署用时会比以往长
|
||||
挺多,因为 Nix 会从源码编译整个 Helix 程序。
|
||||
|
||||
部署完毕后,可直接在终端使用 `hx` 命令测试验证。
|
||||
|
||||
另外,如果你只是想尝试一下 Helix 的最新版本,再决定要不要真正地将它安装到系统里,有更简单
|
||||
的办法,一行命令就行(但如前所述,源码编译会很费时间):
|
||||
|
||||
```bash
|
||||
nix run github:helix-editor/helix/master
|
||||
```
|
||||
|
||||
我们会在后面的 [新一代 Nix 命令行工具的使用](../other-usage-of-flakes/the-new-cli.md) 中详
|
||||
细介绍 `nix run` 的用法。
|
||||
|
||||
## 使用其他 Flakes 包提供的功能
|
||||
|
||||
其实这才是 Flakes 最主要的功能,一个 Flake 可以依赖其他 Flakes,从而使用它们提供的功能——就
|
||||
如同我们在写 TypeScript/Go/Rust 等程序时使用其他 Library 提供的功能一样。
|
||||
|
||||
上面使用 Helix 的官方 Flake 中提供的最新版本就是一个例子,其他更多的用例会在后面提到,这里
|
||||
引用几个后面会讲的例子:
|
||||
|
||||
- [Getting Started with Home Manager](./start-using-home-manager.md): 这里引入了社区的
|
||||
Home-Manager 作为依赖项,从而能直接使用该 Flake 提供的功能。
|
||||
- [Downgrading or Upgrading Packages](./downgrade-or-upgrade-packages.md): 这里引入了不同
|
||||
版本的 Nixpkgs 作为依赖项,从而能很灵活地选用不同版本的 Nixpkgs 中的包。
|
||||
|
||||
|
||||
## 其他 Flakes 学习资料
|
||||
|
||||
到此为止,我们已经学习了如何使用 Flakes 来配置 NixOS 系统。
|
||||
如果你对 Flakes 还有更多的疑问,或者想深入学习,请直接参考如下官方/半官方的文档。
|
||||
|
||||
- Nix Flakes 的官方文档:
|
||||
- [Nix flakes - Nix Manual](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake)
|
||||
- [Flakes - nix.dev](https://nix.dev/concepts/flakes)
|
||||
- Eelco Dolstra (Nix 的创造者)的一系列关于 Flakes 的文章:
|
||||
- [Nix Flakes, Part 1: An introduction and tutorial (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-05-25-flakes/)
|
||||
- [Nix Flakes, Part 2: Evaluation caching (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-06-25-eval-cache/)
|
||||
- [Nix Flakes, Part 3: Managing NixOS systems (Eelco Dolstra, 2020)](https://www.tweag.io/blog/2020-07-31-nixos-flakes/)
|
||||
- 其他可能有用的文档:
|
||||
- [Practical Nix Flakes](https://serokell.io/blog/practical-nix-flakes)
|
||||
|
||||
|
||||
[nix flake - Nix Manual]:
|
||||
https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs
|
||||
[nixpkgs/flake.nix]: https://github.com/NixOS/nixpkgs/tree/nixos-23.11/flake.nix
|
||||
[nixpkgs/nixos/lib/eval-config.nix]:
|
||||
https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/lib/eval-config.nix
|
||||
[Module System - Nixpkgs]:
|
||||
https://github.com/NixOS/nixpkgs/blob/23.11/doc/module-system/module-system.chapter.md
|
||||
[nixpkgs/nixos-23.11/lib/modules.nix - _module.args]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/lib/modules.nix#L122-L184
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/doc/manual/development/option-types.section.md?plain=1#L237-L244
|
171
docs/zh/nixos-with-flakes/nixos-flake-configuration-explained.md
Normal file
171
docs/zh/nixos-with-flakes/nixos-flake-configuration-explained.md
Normal file
@ -0,0 +1,171 @@
|
||||
# `flake.nix` 配置详解 {#flake-nix-configuration-explained}
|
||||
|
||||
上面我们创建了一个 `flake.nix` 文件并通过它来管理系统配置,但你对它的结构还是一头雾水,下
|
||||
面我们来详细解释一下这个文件的内容。
|
||||
|
||||
### 1. flake inputs
|
||||
|
||||
首先看看其中的 `inputs` 属性,它是一个 attribute set,其中定义了这个 flake 的所有依赖项,
|
||||
这些依赖项会在被拉取后,作为参数传递给 `outputs` 函数:
|
||||
|
||||
```nix{2-5,7}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS 官方软件源,这里使用 nixos-23.11 分支
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# 省略掉前面的配置......
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`inputs` 中的每一项依赖有许多类型与定义方式,可以是另一个 flake,也可以是一个普通的 Git 仓
|
||||
库,又或者一个本地路径。
|
||||
[Flakes 的其他玩法 - Flake 的 inputs](../other-usage-of-flakes/inputs.md) 中详细介绍了常见
|
||||
的依赖项类型与定义方式。
|
||||
|
||||
这里我们只定义了 `nixpkgs` 这一个依赖项,使用的是 flake 中最常见的引用方式,即
|
||||
`github:owner/name/reference`,这里的 `reference` 可以是分支名、commit-id 或 tag。
|
||||
|
||||
`nixpkgs` 在 `inputs` 中被定义后,就可以在后面的 `outputs` 函数的参数中使用此依赖项中的内
|
||||
容了,我们的示例中正是这么干的。
|
||||
|
||||
### 2. flake outputs
|
||||
|
||||
再来看看 `outputs`,它是一个以 `inputs` 中的依赖项为参数的函数,函数的返回值是一个
|
||||
attribute set,这个返回的 attribute set 即为该 flake 的构建结果:
|
||||
|
||||
```nix{10-18}
|
||||
{
|
||||
description = "A simple NixOS flake";
|
||||
|
||||
inputs = {
|
||||
# NixOS 官方软件源,这里使用 nixos-23.11 分支
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# hostname 为 my-nixos 的主机会使用这个配置
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
flake 有很多的用途,也可以有很多不同类型的
|
||||
outputs,[Flake 的 outputs](../other-usage-of-flakes/outputs.md) 一节有更详细的介绍。这里
|
||||
我们只用到了 `nixosConfigurations` 这一类型的 outputs,它用于配置 NixOS 系统。
|
||||
|
||||
在我们运行 `sudo nixos-rebuild switch` 命令时,它会从 `/etc/nixos/flake.nix` 的 `outputs`
|
||||
函数返回值中查找 `nixosConfigurations.my-nixos` (其中的 `my-nixos` 将会是你当前系统的
|
||||
hostname)这一属性,并使用其中的定义来配置你的 NixOS 系统。
|
||||
|
||||
实际我们也可以自定义 flake 的位置与 NixOS 配置的名称,而不是使用默认值。只需要在
|
||||
`nixos-rebuild` 命令后面添加 `--flake` 参数即可,一个例子:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake /path/to/your/flake#your-hostname
|
||||
```
|
||||
|
||||
上述命令中的 `--flake /path/to/your/flake#your-hostname` 参数简要说明如下:
|
||||
|
||||
1. `/path/to/your/flake` 为目标 flake 的位置,默认会使用 `/etc/nixos/` 这个路径。
|
||||
2. `#` 是一个分隔符,其后的 `your-hostname` 则是 NixOS 配置的名称。`nixos-rebuild` 默认会
|
||||
以你当前系统的 hostname 为配置名称进行查找。
|
||||
|
||||
你甚至能直接引用一个远程的 GitHub 仓库作为你的 flake 来源,示例如下:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake github:owner/repo#your-hostname
|
||||
```
|
||||
|
||||
### 3. `outputs` 函数的特殊参数 `self` {#special-parameter-self-of-outputs-function}
|
||||
|
||||
虽然我们前面并未提到,但是前面的所有示例代码中,`outputs` 函数都还有一个特殊的参数
|
||||
`self`,这里我们简单介绍一下它的作用。
|
||||
|
||||
[nix flake - Nix Manual] 对其的描述是:
|
||||
|
||||
> The special input named `self` refers to the outputs and source tree of this flake.
|
||||
|
||||
所以说 `self` 是当前 flake 的 `outputs` 函数的返回值,同时也是当前 flake 源码的文件夹路径
|
||||
(source tree)。
|
||||
|
||||
这里我们并未使用到 `self` 这个参数,在后面一些更复杂的例子(或者你网上搜
|
||||
到的一些配置)中,我们会看到 `self` 的用法。
|
||||
|
||||
> 注意:你可能会在一些代码中看到,有人会使用 `self.outputs` 来引用当前 flake 的输出,这
|
||||
> 确实是可行的,但 Nix Manual 并未对其做任何说明,属于是 flake 的内部实现细节,不建议在
|
||||
> 你自己的代码中使用!
|
||||
|
||||
### 4. `nixpkgs.lib.nixosSystem` 函数的简单介绍 {#simple-introduction-to-nixpkgs-lib-nixos-system}
|
||||
|
||||
**一个 Flake 可以依赖其他 Flakes,从而使用它们提供的功能**。
|
||||
|
||||
默认情况下,一个 flake 会在其每个依赖项(即 `inputs` 中的每一项)的根目录下寻找
|
||||
`flake.nix` 文件并**懒惰求值**(lazy evaluation)它们的 `outputs` 函数,接着将这些函数返回
|
||||
的 attribute sets 作为参数传递给它自身的 `outputs` 函数,这样我们就能在当前 flake 中使用它
|
||||
所依赖的其他 flakes 提供的功能了。
|
||||
|
||||
更精确地说,对每个依赖项的 `outputs` 函数的求值都是懒惰(lazy)的,也就是说,一个 flake 的
|
||||
`outputs` 函数只有在被真正使用到的时候才会被求值,这样就能避免不必要的计算,从而提高效率。
|
||||
|
||||
上面的描述可能有点绕,我们还是结合本节中使用的 `flake.nix` 示例来看看这个过程。我们的
|
||||
`flake.nix` 声明了 `inputs.nixpkgs` 这个依赖项,因此 [nixpkgs/flake.nix] 会在我们执行
|
||||
`sudo nixos-rebuild switch` 这个命令时被求值。从 Nixpkgs 仓库的源码中能看到它的 flake
|
||||
outputs 定义中有返回 `lib` 这个属性,我们的例子中就使用了 `lib` 属性中的 `nixosSystem` 这
|
||||
个函数来配置我们的 NixOS 系统:
|
||||
|
||||
```nix{8-13}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS 官方软件源,这里使用 nixos-23.11 分支
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`nixpkgs.lib.nixosSystem` 后面跟的 attribute set 就是该函数的参数,我们这里只设置了两个参
|
||||
数:
|
||||
|
||||
1. `system`: 这个很好懂,就是系统架构参数。
|
||||
2. `modules`: 此函数是一个 modules 的列表,NixOS 的实际系统配置都定义在这些 modules 中。
|
||||
|
||||
`/etc/nixos/configuration.nix` 这个配置文件本身就是一个 Nixpkgs Module,因此可以直接将其添
|
||||
加到 `modules` 列表中使用。
|
||||
|
||||
新手阶段了解这些就足够了,探究 `nixpkgs.lib.nixosSystem` 函数的具体实现需要对 Nixpkgs 的模
|
||||
块系统有一定的了解。读者可以在学习了
|
||||
[模块化 NixOS 配置](./modularize-the-configuration.md) 一节后,再回过头来从
|
||||
[nixpkgs/flake.nix] 中找到 `nixpkgs.lib.nixosSystem` 的定义,跟踪它的源码,研究其实现方
|
||||
式。
|
||||
|
||||
|
||||
[nix flake - Nix Manual]:
|
||||
https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs
|
||||
[nixpkgs/flake.nix]: https://github.com/NixOS/nixpkgs/tree/nixos-23.11/flake.nix
|
||||
[nixpkgs/nixos/lib/eval-config.nix]:
|
||||
https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/lib/eval-config.nix
|
||||
[Module System - Nixpkgs]:
|
||||
https://github.com/NixOS/nixpkgs/blob/23.11/doc/module-system/module-system.chapter.md
|
||||
[nixpkgs/nixos-23.11/lib/modules.nix - _module.args]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/lib/modules.nix#L122-L184
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]:
|
||||
https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/doc/manual/development/option-types.section.md?plain=1#L237-L244
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
# 使用 Flakes 来管理你的 NixOS
|
||||
|
||||
## 启用 NixOS 的 Flakes 支持 {#enable-nix-flakes}
|
||||
|
||||
与 NixOS 当前默认的配置方式相比,Flakes 提供了更好的可复现性,同时它清晰的包结构定义原生支
|
||||
持了以其他 Git 仓库为依赖,便于代码分享,因此本书更建议使用 Flakes 来管理系统配置。
|
||||
|
||||
目前 Flakes 作为一个实验特性,仍未被默认启用,我们需要手动修改
|
||||
本节我们介绍如何使用 Flakes 来管理 NixOS 系统配置,**阅读本节内容不需要提前对 Flakes 有任
|
||||
何了解**。
|
||||
|
||||
## 启用 NixOS 的 Flakes 支持 {#enable-nix-flakes}
|
||||
|
||||
目前 Flakes 作为一个实验特性,仍未被默认启用,因此我们需要先手动修改
|
||||
`/etc/nixos/configuration.nix` 文件,启用 Flakes 特性以及配套的船新 nix 命令行工具:
|
||||
|
||||
```nix{12,15}
|
||||
@ -103,9 +106,14 @@ cat flake.nix
|
||||
- `/etc/nixos/hardware-configuration.nix`: 这是系统硬件配置文件,由 NixOS 生成,描述了系统
|
||||
的硬件信息
|
||||
|
||||
到这里为止, `/etc/nixos/flake.nix` 仅仅是 `/etc/nixos/configuration.nix` 的一个 thin
|
||||
wrapper,它自身并没有提供任何新的功能,也没有引入任何破坏性的变更。在本书后面的内容中,我
|
||||
们会逐渐看到这样一个 wrapper 带来了哪些好处。
|
||||
## 总结 {#conclusion}
|
||||
|
||||
本节中我们添加了一个非常简单的配置文件 `/etc/nixos/flake.nix`,它仅仅是
|
||||
`/etc/nixos/configuration.nix` 的一个 thin wrapper,它自身并没有提供任何新的功能,也没有引
|
||||
入任何破坏性的变更。
|
||||
|
||||
在本书后面的内容中,我们会学习了解 `flake.nix` 的结构与功能,并逐渐看到这样一个 wrapper 能
|
||||
为我们带来哪些好处。
|
||||
|
||||
> 注意:**本书描述的配置管理方式并非「Everything in a single file」,更推荐将配置内容分门
|
||||
> 别类地存放到不同的 nix 文件中**,然后在 `flake.nix` 的 `modules` 参数列表中引入这些配置
|
||||
@ -114,402 +122,6 @@ wrapper,它自身并没有提供任何新的功能,也没有引入任何破
|
||||
> 你的 NixOS 配置,[其他实用技巧 - 使用 Git 管理 NixOS 配置](./other-useful-tips.md) 将会
|
||||
> 介绍几种使用 Git 管理 NixOS 配置的最佳实践。
|
||||
|
||||
## `flake.nix` 配置详解 {#flake-nix-configuration-explained}
|
||||
|
||||
上面我们创建了一个 `flake.nix` 文件并通过它来管理系统配置,但你对它的结构还是一头雾水,下
|
||||
面我们来详细解释一下这个文件的内容。
|
||||
|
||||
### 1. flake inputs
|
||||
|
||||
首先看看其中的 `inputs` 属性,它是一个 attribute set,其中定义了这个 flake 的所有依赖项,
|
||||
这些依赖项会在被拉取后,作为参数传递给 `outputs` 函数:
|
||||
|
||||
```nix{2-5,7}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS 官方软件源,这里使用 nixos-23.11 分支
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# 省略掉前面的配置......
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`inputs` 中的每一项依赖有许多类型与定义方式,可以是另一个 flake,也可以是一个普通的 Git 仓
|
||||
库,又或者一个本地路径。
|
||||
[Flakes 的其他玩法 - Flake 的 inputs](../other-usage-of-flakes/inputs.md) 中详细介绍了常见
|
||||
的依赖项类型与定义方式。
|
||||
|
||||
这里我们只定义了 `nixpkgs` 这一个依赖项,使用的是 flake 中最常见的引用方式,即
|
||||
`github:owner/name/reference`,这里的 `reference` 可以是分支名、commit-id 或 tag。
|
||||
|
||||
`nixpkgs` 在 `inputs` 中被定义后,就可以在后面的 `outputs` 函数的参数中使用此依赖项中的内
|
||||
容了,我们的示例中正是这么干的。
|
||||
|
||||
### 2. flake outputs
|
||||
|
||||
再来看看 `outputs`,它是一个以 `inputs` 中的依赖项为参数的函数,函数的返回值是一个
|
||||
attribute set,这个返回的 attribute set 即为该 flake 的构建结果:
|
||||
|
||||
```nix{10-18}
|
||||
{
|
||||
description = "A simple NixOS flake";
|
||||
|
||||
inputs = {
|
||||
# NixOS 官方软件源,这里使用 nixos-23.11 分支
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
# hostname 为 my-nixos 的主机会使用这个配置
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
flake 有很多的用途,也可以有很多不同类型的
|
||||
outputs,[Flake 的 outputs](../other-usage-of-flakes/outputs.md) 一节有更详细的介绍。这里
|
||||
我们只用到了 `nixosConfigurations` 这一类型的 outputs,它用于配置 NixOS 系统。
|
||||
|
||||
在我们运行 `sudo nixos-rebuild switch` 命令时,它会从 `/etc/nixos/flake.nix` 的 `outputs`
|
||||
函数返回值中查找 `nixosConfigurations.my-nixos` (其中的 `my-nixos` 将会是你当前系统的
|
||||
hostname)这一属性,并使用其中的定义来配置你的 NixOS 系统。
|
||||
|
||||
实际我们也可以自定义 flake 的位置与 NixOS 配置的名称,而不是使用默认值。只需要在
|
||||
`nixos-rebuild` 命令后面添加 `--flake` 参数即可,一个例子:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake /path/to/your/flake#your-hostname
|
||||
```
|
||||
|
||||
上述命令中的 `--flake /path/to/your/flake#your-hostname` 参数简要说明如下:
|
||||
|
||||
1. `/path/to/your/flake` 为目标 flake 的位置,默认会使用 `/etc/nixos/` 这个路径。
|
||||
2. `#` 是一个分隔符,其后的 `your-hostname` 则是 NixOS 配置的名称。`nixos-rebuild` 默认会
|
||||
以你当前系统的 hostname 为配置名称进行查找。
|
||||
|
||||
你甚至能直接引用一个远程的 GitHub 仓库作为你的 flake 来源,示例如下:
|
||||
|
||||
```nix
|
||||
sudo nixos-rebuild switch --flake github:owner/repo#your-hostname
|
||||
```
|
||||
|
||||
### 3. `outputs` 函数的特殊参数 `self` {#special-parameter-self-of-outputs-function}
|
||||
|
||||
虽然我们前面并未提到,但是前面的所有示例代码中,`outputs` 函数都还有一个特殊的参数
|
||||
`self`,这里我们简单介绍一下它的作用。
|
||||
|
||||
[nix flake - Nix Manual] 对其的描述是:
|
||||
|
||||
> The special input named `self` refers to the outputs and source tree of this flake.
|
||||
|
||||
所以说 `self` 是当前 flake 的 `outputs` 函数的返回值,同时也是当前 flake 源码的文件夹路径
|
||||
(source tree)。
|
||||
|
||||
这里我们并未使用到 `self` 这个参数,在后面一些更复杂的例子(或者你网上搜
|
||||
到的一些配置)中,我们会看到 `self` 的用法。
|
||||
|
||||
> 注意:你可能会在一些代码中看到,有人会使用 `self.outputs` 来引用当前 flake 的输出,这
|
||||
> 确实是可行的,但 Nix Manual 并未对其做任何说明,属于是 flake 的内部实现细节,不建议在
|
||||
> 你自己的代码中使用!
|
||||
|
||||
### 4. `nixpkgs.lib.nixosSystem` 函数的简单介绍 {#simple-introduction-to-nixpkgs-lib-nixos-system}
|
||||
|
||||
**一个 Flake 可以依赖其他 Flakes,从而使用它们提供的功能**。
|
||||
|
||||
默认情况下,一个 flake 会在其每个依赖项(即 `inputs` 中的每一项)的根目录下寻找
|
||||
`flake.nix` 文件并**懒惰求值**(lazy evaluation)它们的 `outputs` 函数,接着将这些函数返回
|
||||
的 attribute sets 作为参数传递给它自身的 `outputs` 函数,这样我们就能在当前 flake 中使用它
|
||||
所依赖的其他 flakes 提供的功能了。
|
||||
|
||||
更精确地说,对每个依赖项的 `outputs` 函数的求值都是懒惰(lazy)的,也就是说,一个 flake 的
|
||||
`outputs` 函数只有在被真正使用到的时候才会被求值,这样就能避免不必要的计算,从而提高效率。
|
||||
|
||||
上面的描述可能有点绕,我们还是结合本节中使用的 `flake.nix` 示例来看看这个过程。我们的
|
||||
`flake.nix` 声明了 `inputs.nixpkgs` 这个依赖项,因此 [nixpkgs/flake.nix] 会在我们执行
|
||||
`sudo nixos-rebuild switch` 这个命令时被求值。从 Nixpkgs 仓库的源码中能看到它的 flake
|
||||
outputs 定义中有返回 `lib` 这个属性,我们的例子中就使用了 `lib` 属性中的 `nixosSystem` 这
|
||||
个函数来配置我们的 NixOS 系统:
|
||||
|
||||
```nix{8-13}
|
||||
{
|
||||
inputs = {
|
||||
# NixOS 官方软件源,这里使用 nixos-23.11 分支
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`nixpkgs.lib.nixosSystem` 后面跟的 attribute set 就是该函数的参数,我们这里只设置了两个参
|
||||
数:
|
||||
|
||||
1. `system`: 这个很好懂,就是系统架构参数。
|
||||
2. `modules`: 此函数是一个 modules 的列表,NixOS 的实际系统配置都定义在这些 modules 中。
|
||||
|
||||
`/etc/nixos/configuration.nix` 这个配置文件本身就是一个 Nixpkgs Module,因此可以直接将其添
|
||||
加到 `modules` 列表中使用。
|
||||
|
||||
新手阶段了解这些就足够了,探究 `nixpkgs.lib.nixosSystem` 函数的具体实现需要对 Nixpkgs 的模
|
||||
块系统有一定的了解。读者可以在学习了
|
||||
[模块化 NixOS 配置](./modularize-the-configuration.md) 一节后,再回过头来从
|
||||
[nixpkgs/flake.nix] 中找到 `nixpkgs.lib.nixosSystem` 的定义,跟踪它的源码,研究其实现方
|
||||
式。
|
||||
|
||||
## Nixpkgs Module 结构的简单介绍 {#simple-introduction-to-nixpkgs-module-structure}
|
||||
|
||||
> 在后面的 [模块化 NixOS 配置](./modularize-the-configuration.md) 一节中会详细介绍这套模块
|
||||
> 系统的工作方式,这里只介绍些基础知识。
|
||||
|
||||
为什么 `/etc/nixos/configuration.nix` 这个配置文件会符合 Nixpkgs Module 定义,从而能直接在
|
||||
`flake.nix` 中引用它呢?可能会有读者觉得这有点出乎意料。
|
||||
|
||||
这实际是因为 Nixpkgs 中包含了大量 NixOS 的实现源码,这些源码大都使用 Nix 语言编写。为了编
|
||||
写维护如此多的 Nix 代码,并且使用户能灵活地自定义其 NixOS 系统的各项功能,就必须要有一套
|
||||
Nix 代码的模块化系统。
|
||||
|
||||
这套 Nix 代码的模块系统的实现也同样在 Nixpkgs 仓库中,它主要被用于 NixOS 系统配置的模块
|
||||
化,但也有其他的应用,比如 nix-darwin 跟 home-manager 都大量使用了这套模块系统。
|
||||
|
||||
既然 NixOS 是基于这套模块系统构建的,那它的配置文件(包括 `/etc/nixos/configuration.nix`)
|
||||
是一个Nixpkgs Module,也就显得非常自然了。
|
||||
|
||||
在学习后面的内容之前,我们需要先简单了解下这套模块系统的工作方式。
|
||||
|
||||
一个简化的 Nixpkgs Module 结构如下:
|
||||
|
||||
```nix
|
||||
{lib, config, options, pkgs, ...}:
|
||||
{
|
||||
# 导入其他 Modules
|
||||
imports = [
|
||||
# ......
|
||||
# ./xxx.nix
|
||||
];
|
||||
|
||||
for.bar.enable = true;
|
||||
# other options declarations
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
可以看到它的定义实际是一个 Nix 函数,该函数有 5 个**由模块系统自动生成、自动注入、无需额外
|
||||
声明的参数**:
|
||||
|
||||
1. `lib`: **nixpkgs 自带的函数库,提供了许多操作 Nix 表达式的实用函数**
|
||||
- 详见 <https://nixos.org/manual/nixpkgs/stable/#id-1.4>
|
||||
2. `config`: 包含了当前环境中所有 option 的值,在后面学习模块系统时会大量使用它
|
||||
3. `options`: 当前环境中所有 Modules 中定义的所有 options 的集合
|
||||
4. `pkgs`: **一个包含所有 nixpkgs 包的集合,它也提供了许多相关的工具函数**
|
||||
- 入门阶段可以认为它的默认值为 `nixpkgs.legacyPackages."${system}"`,可通过
|
||||
`nixpkgs.pkgs` 这个 option 来自定义 `pkgs` 的值
|
||||
5. `modulesPath`: 一个只在 NixOS 中可用的参数,是一个 Path,指向
|
||||
[nixpkgs/nixos/modules](https://github.com/NixOS/nixpkgs/tree/nixos-23.11/nixos/modules)
|
||||
- 它在
|
||||
[nixpkgs/nixos/lib/eval-config-minimal.nix#L43](https://github.com/NixOS/nixpkgs/blob/nixos-23.11/nixos/lib/eval-config-minimal.nix#L43)
|
||||
中被定义
|
||||
- 通常被用于导入一些额外的 NixOS 模块,NixOS 自动生成的 `hardware-configuration.nix` 中
|
||||
基本都能看到它
|
||||
|
||||
## 传递非默认参数到模块系统中 {#pass-non-default-parameters-to-submodules}
|
||||
|
||||
而如果你需要将其他非默认参数传递到子模块,就需要使用一些特殊手段手动指定这些非默认参数。
|
||||
|
||||
Nixpkgs 的模块系统提供了两种方式来传递非默认参数:
|
||||
|
||||
1. `nixpkgs.lib.nixosSystem` 函数的 `specialArgs` 参数
|
||||
1. 在任一 Module 中使用 `_module.args` 这个 option 来传递参数
|
||||
|
||||
这两个参数的官方文档藏得很深,而且语焉不详、晦涩难懂。读者感兴趣的话我把链接放在这里:
|
||||
|
||||
1. `specialArgs`: NixOS Manual 跟 Nixpkgs Manual 中分别有与它有关的只言片语
|
||||
- Nixpkgs Manual: [Module System - Nixpkgs]
|
||||
- NixOS Manual:
|
||||
[nixpkgs/nixos-23.11/nixos/doc/manual/development/option-types.section.md#L237-L244]
|
||||
1. `_module.args`:
|
||||
- NixOS Manual:
|
||||
[Appendix A. Configuration Options](https://nixos.org/manual/nixos/stable/options#opt-_module.args)
|
||||
- Source Code: [nixpkgs/nixos-23.11/lib/modules.nix - _module.args]
|
||||
|
||||
总之,`specialArgs` 与 `_module.args` 需要的值都是一个 attribute set,它们的功能也相同,都
|
||||
是将其 attribute set 中的所有参数传递到所有子模块中。这两者的区别在于:
|
||||
|
||||
1. 在任何 Module 中都能使用 `_module.args` 这个 option,通过它互相传递参数,这要比只能在
|
||||
`nixpkgs.lib.nixosSystem` 函数中使用的 `specialArgs` 更灵活。
|
||||
1. `_module.args` 是在 Module 中声明使用的,因此必须在所有 Modules 都已经被求值后,才能使
|
||||
用它。这导致**如果你在 `imports = [ ... ];` 中使用 `_module.args` 传递的参数,会报错
|
||||
`infinite recursion`,这种场景下你必须改用 `specialArgs` 才行**。
|
||||
|
||||
NixOS 社区比较推荐优先使用 `_module.args` 这个 options,仅在无法使用 `_module.args` 时才改
|
||||
用 `specialArgs`。
|
||||
|
||||
假设你想将某个依赖项传递到子模块中使用,可以使用 `specialArgs` 参数将 `inputs` 传递到所有
|
||||
子模块中:
|
||||
|
||||
```nix{13}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
# 将所有 inputs 参数设为所有子模块的特殊参数,
|
||||
# 这样就能直接在子模块中使用 inputs 中的所有依赖项了
|
||||
specialArgs = { inherit inputs;};
|
||||
modules = [
|
||||
./configuration.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
或者使用 `_module.args` 这个 option 也能达成同样的效果:
|
||||
|
||||
```nix{15}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
another-input.url = "github:username/repo-name/branch-name";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, another-input, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
{
|
||||
# 将所有 inputs 参数设为所有子模块的特殊参数,
|
||||
# 这样就能直接在子模块中使用 inputs 中的所有依赖项了
|
||||
_module.args = { inherit inputs; };
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
选择上述两种方式之一修改你的配置,然后在 `/etc/nixos/configuration.nix` 中就可以使用
|
||||
`inputs` 这个参数了,模块系统会自动匹配到 `specialArgs` 中定义的 `inputs`,并将其注入到所
|
||||
有需要该参数的子模块中:
|
||||
|
||||
```nix{3}
|
||||
# Nix 会通过名称匹配,
|
||||
# 自动将 specialArgs/_module.args 中的 inputs 注入到此函数的第三个参数
|
||||
{ config, pkgs, inputs, ... }:
|
||||
|
||||
# 然后我们就能在这下面使用 inputs 这个参数了
|
||||
{
|
||||
# ......
|
||||
}
|
||||
```
|
||||
|
||||
下一节将演示如何使用 `specialArgs`/`_module.args` 来从其他 flake 来源安装系统软件。
|
||||
|
||||
## 从其他 flake 来源安装系统软件 {#install-system-packages-from-other-flakes}
|
||||
|
||||
管系统最常见的需求就是装软件,我们在上一节已经见识过如何通过 `environment.systemPackages`
|
||||
来安装 `pkgs` 中的包,这些包都来自官方的 nixpkgs 仓库。
|
||||
|
||||
现在我们学习下如何安装其他 flake 来源的软件包,这比直接从 nixpkgs 安装要灵活很多,最主要的
|
||||
用途是安装 Nixpkgs 中还未添加或未更新的某软件的最新版本。
|
||||
|
||||
以 [helix](https://github.com/helix-editor/helix) 编辑器为例,这里演示下如何直接编译安装
|
||||
helix 的 master 分支。
|
||||
|
||||
首先在 `flake.nix` 中添加 helix 这个 inputs 数据源:
|
||||
|
||||
```nix{6,12,18}
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
|
||||
# helix editor, use the master branch
|
||||
helix.url = "github:helix-editor/helix/master";
|
||||
};
|
||||
|
||||
outputs = inputs@{ self, nixpkgs, ... }: {
|
||||
nixosConfigurations.my-nixos = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = { inherit inputs;};
|
||||
modules = [
|
||||
./configuration.nix
|
||||
|
||||
# 如下 Module 与前面的 `specialArgs` 参数功能完全一致
|
||||
# 选择其中一种即可
|
||||
# { _module.args = { inherit inputs; };}
|
||||
];
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
接下来在 `configuration.nix` 中就能引用这个 flake input 数据源了:
|
||||
|
||||
```nix{1,10}
|
||||
{ config, pkgs, inputs, ... }:
|
||||
{
|
||||
# 省略无关配置......
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
wget
|
||||
curl
|
||||
# 这里从 helix 这个 inputs 数据源安装了 helix 程序
|
||||
inputs.helix.packages."${pkgs.system}".helix
|
||||
];
|
||||
# 省略其他配置......
|
||||
}
|
||||
```
|
||||
|
||||
改好后再 `sudo nixos-rebuild switch` 部署,就能安装好 Helix 程序了。这次部署用时会比以往长
|
||||
挺多,因为 Nix 会从源码编译整个 Helix 程序。
|
||||
|
||||
部署完毕后,可直接在终端使用 `hx` 命令测试验证。
|
||||
|
||||
另外,如果你只是想尝试一下 Helix 的最新版本,再决定要不要真正地将它安装到系统里,有更简单
|
||||
的办法,一行命令就行(但如前所述,源码编译会很费时间):
|
||||
|
||||
```bash
|
||||
nix run github:helix-editor/helix/master
|
||||
```
|
||||
|
||||
我们会在后面的 [新一代 Nix 命令行工具的使用](../other-usage-of-flakes/the-new-cli.md) 中详
|
||||
细介绍 `nix run` 的用法。
|
||||
|
||||
## 使用其他 Flakes 包提供的功能
|
||||
|
||||
其实这才是 Flakes 最主要的功能,一个 Flake 可以依赖其他 Flakes,从而使用它们提供的功能——就
|
||||
如同我们在写 TypeScript/Go/Rust 等程序时使用其他 Library 提供的功能一样。
|
||||
|
||||
上面使用 Helix 的官方 Flake 中提供的最新版本就是一个例子,其他更多的用例会在后面提到,这里
|
||||
引用几个后面会讲的例子:
|
||||
|
||||
- [Getting Started with Home Manager](./start-using-home-manager.md): 这里引入了社区的
|
||||
Home-Manager 作为依赖项,从而能直接使用该 Flake 提供的功能。
|
||||
- [Downgrading or Upgrading Packages](./downgrade-or-upgrade-packages.md): 这里引入了不同
|
||||
版本的 Nixpkgs 作为依赖项,从而能很灵活地选用不同版本的 Nixpkgs 中的包。
|
||||
|
||||
[nix flake - Nix Manual]:
|
||||
https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs
|
||||
[nixpkgs/flake.nix]: https://github.com/NixOS/nixpkgs/tree/nixos-23.11/flake.nix
|
||||
|
Loading…
Reference in New Issue
Block a user