Overlays
The override
we introduced earlier generates a new Derivation that does not affect the original Derivation in pkgs
. It's only suitable for use as a local parameter. If you need to override a Derivation that is also dependent on other Nix packages, then other Nix packages will still use the original Derivation.
To solve this problem, Nix provides the ability to use overlays
. Simply put, overlays
can globally modify the Derivations in pkgs
.
In the classic Nix environment, Nix automatically applies all overlays
configurations under the paths ~/.config/nixpkgs/overlays.nix
and ~/.config/nixpkgs/overlays/*.nix
. However, in Flakes, to ensure the reproducibility of the system, it cannot depend on any configuration outside the Git repository. Therefore, this classic method cannot be used now.
When using Flakes to write configuration for NixOS, both home Manager and NixOS provide the nixpkgs.overlays
option to define overlays
. For more information, refer to the following documentation:
For example, the following content is a Module that loads overlays, which can be used as either a home Manager Module or a NixOS Module because the two definitions are exactly the same:
Home Manager is an external component, and most people use the unstable branch of Home Manager and nixpkgs, which sometimes causes problems with Home Manager Module. Therefore, it's recommended to import
overlays
in a NixOS Module.
{ config, pkgs, lib, ... }:
{
nixpkgs.overlays = [
# overlayer1 - use self and super to express the inheritance relationship
(self: super: {
google-chrome = super.google-chrome.override {
commandLineArgs =
"--proxy-server='https=127.0.0.1:3128;http=127.0.0.1:3128'";
};
})
# overlayer2 - you can also use `extend` to inherit other overlays
# use `final` and `prev` to express the relationship between the new and the old
(final: prev: {
steam = prev.steam.override {
extraPkgs = pkgs:
with pkgs; [
keyutils
libkrb5
libpng
libpulseaudio
libvorbis
stdenv.cc.cc.lib
xorg.libXcursor
xorg.libXi
xorg.libXinerama
xorg.libXScrnSaver
];
extraProfile = "export GDK_SCALE=2";
};
})
# overlay3 - define overlays in other files
# here the content of overlay3.nix is the same as above:
# `final: prev: { xxx = prev.xxx.override { ... }; }`
(import ./overlays/overlay3.nix)
];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
refer to this example to write your own overlays, import the configuration as a NixOS Module or a home Manager Module, and then deploy it to see the effect.
Modular overlays
The previous example shows how to write overlays, but all overlays are written in a single nix file, which is a bit difficult to maintain.
To resolve this problem, here is a best practice of how to manage overlays in a modular way.
First, create an overlays
folder in the Git repository to store all overlays configurations, and then create overlays/default.nix
, whose content is as follows:
args:
# import all nix files in the current folder, and execute them with args as parameters
# The return value is a list of all execution results, which is the list of overlays
builtins.map
(f: (import (./. + "/${f}") args)) # the first parameter of map, a function that import and execute a nix file
(builtins.filter # the second parameter of map, a list of all nix files in the current folder except default.nix
(f: f != "default.nix")
(builtins.attrNames (builtins.readDir ./.)))
2
3
4
5
6
7
8
Then you can write all overlays configurations in the overlays
folder, an example configuration overlays/fcitx5/default.nix
is as follows:
# to add my custom input method, I override the default rime-data here
# refer to https://github.com/NixOS/nixpkgs/blob/e4246ae1e7f78b7087dce9c9da10d28d3725025f/pkgs/tools/inputmethods/fcitx5/fcitx5-rime.nix
{pkgs, config, lib, ...}:
(self: super: {
# my custom input method's rime-data, downloaded from https://flypy.com
rime-data = ./rime-data-flypy;
fcitx5-rime = super.fcitx5-rime.override { rimeDataPkgs = [ ./rime-data-flypy ]; };
})
2
3
4
5
6
7
8
9
We customized the rime-data
package through the overlay shown above.
At last, you need to load all overlays returned by overlays/default.nix
through the nixpkgs.overlays
option, add the following parameter to any NixOS Module to achieve this:
{ config, pkgs, lib, ... } @ args:
{
# ......
# add this parameter
nixpkgs.overlays = import /path/to/overlays/dir;
# ......
}
2
3
4
5
6
7
8
9
10
For example, you can just add it directly in flake.nix
:
{
description = "NixOS configuration of Ryan Yin";
# ......
inputs = {
# ......
};
outputs = inputs@{ self, nixpkgs, ... }: {
nixosConfigurations = {
nixos-test = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = inputs;
modules = [
./hosts/nixos-test
# add the following inline module definition
# here, all parameters of modules are passed to overlays
(args: { nixpkgs.overlays = import ./overlays args; })
# ......
];
};
};
};
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
By using this modular approach, it is very convenient to modularize all your overlays. Taking my configuration as an example, the structure of the overlays
folder is rough as follows:
.
├── flake.lock
├── flake.nix
├── home
├── hosts
├── modules
├── ......
├── overlays
│ ├── default.nix # it returns a list of all overlays.
│ └── fcitx5 # fcitx5 overlay
│ ├── default.nix
│ ├── README.md
│ └── rime-data-flypy # my custom rime-data
│ └── share
│ └── rime-data
│ ├── ...... # rime-data files
└── README.md
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17