3.5 KiB
Notes for 7th of June, 2023
Those are my notes on extending nixpkgs with your own functions and abstractions. There may be other ways of doing it, but this is the one I find to be most ergonomic.
What is nixpkgs.lib
In the context of the Nix package manager and NixOS, nixpkgs.lib
refers to
a module within the Nixpkgs repository. The nixpkgs.lib
module provides a
set of utility functions and definitions that are commonly used across the
Nixpkgs repository. It contains various helper functions and abstractions that
make it easier to write Nix expressions and define packages. We often use those
functions to simplify our configurations and the nix package build processes.
Why would you need to extend nixpkgs.lib
While the library functions provided by nixpkgs is quite extensive and usually
suits my needs, I sometimes feel the need to define my own function or wrap an
existing function to complete a task. Normally we can handle the process of a
function inside a simple let in
and be well off, but there may be times you
need to re-use the existing function across your configuration file.
In such times, you might want to either write your own lib and inherit it at
the source of your flake.nix
to then inherit them across your configuration.
Today's notes document the process of doing exactly that.
Extending nixpkgs.lib
I find the easiest way of extending nixpkgs.lib to be using an overlay.
# lib/default.nix
{
nixpkgs,
lib,
inputs,
...
}: nixpkgs.lib.extend (
final: prev: {
# your functions go here
}
)
The above structure takes the existing lib
from nixpkgs
, and appends your
own configurations to it. You may then import this library in your flake.nix
to pass it to other imports and definitions.
# flake.nix
flake = let
# extended nixpkgs lib, contains my custom functions
lib = import ./lib {inherit nixpkgs lib inputs;};
in {
# entry-point for nixos configurations
nixosConfigurations = import ./hosts {inherit nixpkgs self lib;};
};
In this example (see my flake.nix
for the actual implementation) I import my
extended lib from lib/default.nix
, where I defined the overlay. I then pass
the extended lib to my nixosConfiguratiıns
, which is an entry-point for all
of my NixOS configurations. As such, I am able to re-use my own utility
functions across my system as I see fit.
The problem with this approach is that it may be confusing for other people
reviewing your configuration. With this approach, lib.customFunction
looks
identical to any lib function, which may lead to people thinking the function
exists in nixpkgs itself while it is only provided by your configuration. The
solution for that is simple though, instead of extending nixpkgs.lib
, you may
define your own lib that does not inherit from nixpkgs.lib
and only contains
your functions. The process would be similar, and you would not need to define
an overlay.
# flake.nix
flake = let
# extended nixpkgs lib, contains my custom functions
lib' = import ./lib {inherit nixpkgs lib inputs;};
in {
# entry-point for nixos configurations
nixosConfigurations = import ./hosts {inherit nixpkgs self lib';};
};
where your lib/default.nix
looks like
# lib/default.nix
{
nixpkgs,
lib,
inputs,
...
}: {
# your functions here
}
You can find a real life example of the alternative approach in my neovim-flake's lib.