Overlays: Difference between revisions

From NixOS Wiki
imported>Mickours
(Add python package override)
imported>Netvl
(There is no need to manually evaluate nixos-config; it is sufficient to load <nixpkgs/nixos> which will evaluate the config object automatically)
Line 55: Line 55:
===== Using <tt>nixpkgs.overlays</tt> from <tt>configuration.nix</tt> as <tt><nixpkgs-overlays></tt> in your NIX_PATH =====
===== Using <tt>nixpkgs.overlays</tt> from <tt>configuration.nix</tt> as <tt><nixpkgs-overlays></tt> in your NIX_PATH =====


This will allow all the Nix tools to see the exact same overlay as is defined in your <tt>configuration.nix</tt> in the {{nixos:option|nixpkgs.overlays}} option.
Configuration below will allow all of the Nix tools to see the exact same overlay as is defined in your <tt>configuration.nix</tt> in the {{nixos:option|nixpkgs.overlays}} option.


In <tt>configuration.nix</tt>, depending on whether your <tt>configuration.nix</tt> already defines <code>nix.nixPath</code>, add one of those definitions:
The core of the idea here is to point the <code>nixpkgs-overlays</code> element of <code>NIX_PATH</code> to a "compatibility" overlay, which will load all of the overlays defined in your NixOS system configuration and apply them to its own input. Thus, when various Nix tools attempt to load the overlays from the <code>nixpkgs-overlays</code> element of <code>NIX_PATH</code>, they will get contents of overlays defined in your NixOS system config.
 
First, in the <tt>configuration.nix</tt> file, depending on whether your <tt>configuration.nix</tt> already defines <code>nix.nixPath</code>, add one of these definitions:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{ config, pkgs, options, ... }: {
{ config, pkgs, options, ... }: {
   # With existing `nix.nixPath` entry:
   # With an existing `nix.nixPath` entry:
   nix.nixPath = [
   nix.nixPath = [
     # Add the following to existing entries.
     # Add the following to existing entries.
     "nixpkgs-overlays=/etc/nixos/overlays-compat/"
     "nixpkgs-overlays=/etc/nixos/overlays-compat/"
   ];
   ];
   # Without any `nix.nixPath` entry:
   # Without any `nix.nixPath` entry:
   nix.nixPath =
   nix.nixPath =
Line 76: Line 79:
</syntaxhighlight>
</syntaxhighlight>


And, add the file <tt>/etc/nixos/overlays-compat/overlays.nix</tt><ref>[https://gitlab.com/samueldr/nixos-configuration/blob/3febd83b15210282d6435932944d426cd0a9e0ca/modules/overlays-compat/overlays.nix [[User:samueldr|@samueldr]]'s configuration: overlays-compat]</ref>:
Then, add the following contents to <tt>/etc/nixos/overlays-compat/overlays.nix</tt><ref>Based on [https://gitlab.com/samueldr/nixos-configuration/blob/3febd83b15210282d6435932944d426cd0a9e0ca/modules/overlays-compat/overlays.nix [[User:samueldr|@samueldr]]'s configuration: overlays-compat]</ref>:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
Line 82: Line 85:
with super.lib;
with super.lib;
let
let
   # Using the nixos plumbing that's used to evaluate the config...
   # Load the system config and get the `nixpkgs.overlays` option
   eval = import <nixpkgs/nixos/lib/eval-config.nix>;
   overlays = (import <nixpkgs/nixos> { }).config.nixpkgs.overlays;
  # Evaluate the config,
  paths = (eval {modules = [(import <nixos-config>)];})
    # then get the `nixpkgs.overlays` option.
    .config.nixpkgs.overlays
  ;
in
in
foldl' (flip extends) (_: super) paths self
  # Apply all overlays to the input of the current "main" overlay
  foldl' (flip extends) (_: super) overlays self
</syntaxhighlight>
</syntaxhighlight>
The <tt>/etc/nixos/overlays-compat</tt> directory should contain a single <tt>overlays.nix</tt> file to be understood by the Nix tooling, but the location of this directory can be arbitrary, as long as it is set correctly in the <code>nix.nixPath</code> option.


== External Documentation ==
== External Documentation ==

Revision as of 07:37, 14 May 2020

Overlays provide a method to extend and change nixpkgs. They replace constructs like packageOverride and overridePackages.

Consider a simple example of setting the default proxy in Google Chrome:

let overlay1 = self: super:
{
   google-chrome = super.google-chrome.override {
     commandLineArgs =
       "--proxy-server='https=127.0.0.1:3128;http=127.0.0.1:3128'";
   };
};

Data flow of overlays

The data flow around overlays, especially regarding super and self arguments can be a bit confusing if you are not familiar with how overlays work. This graph below hopefully illustrate the data flow better:

Here the main package set is extended with two overlays, ext-1 and ext-2. x // y is represented by a // box with x coming in from the left and y from above.

As you can see, self is the same for every stage, but super comes from only the stage before. So when you define an attribute foo in the set to override it, within that overlay self.foo will be it's version, and super.foo will be the non-overriden version. This is why you see patterns like foo = super.foo.override { ... }.

The names self and super might remind you of inheritance in object-oriented languages. In fact, overlays are exactly the same thing as subclasses, with regards to overriding and calling methods. This data flow is also how objects know which method to call. This is probably why the two arguments got their names, too.

Using overlays

Applying overlays manually

import <nixpkgs> { overlays = [ overlay1 overlay2 ]; }

Applying overlays automatically

On the user level

A list of overlays placed into ~/.config/nixpkgs/overlays.nix will be automatically loaded by all nix tools.

Alternatively, you can put each overlay in its own .nix file under your ~/.config/nixpkgs/overlays directory.

On the system level

If you want your overlays to be accessible by nix tools and also in the system-wide configuration, add nixpkgs-overlays to your NIX_PATH:

NIX_PATH="$NIX_PATH:nixpkgs-overlays=/etc/nixos/overlays"

Currently nixos-rebuild only works with a <nixpkgs-overlays> path that is a directory.

There is a configuration option nixpkgs.overlays. Overlays set here will not be automatically applied by nix tools.

Using nixpkgs.overlays from configuration.nix as <nixpkgs-overlays> in your NIX_PATH

Configuration below will allow all of the Nix tools to see the exact same overlay as is defined in your configuration.nix in the nixpkgs.overlays option.

The core of the idea here is to point the nixpkgs-overlays element of NIX_PATH to a "compatibility" overlay, which will load all of the overlays defined in your NixOS system configuration and apply them to its own input. Thus, when various Nix tools attempt to load the overlays from the nixpkgs-overlays element of NIX_PATH, they will get contents of overlays defined in your NixOS system config.

First, in the configuration.nix file, depending on whether your configuration.nix already defines nix.nixPath, add one of these definitions:

{ config, pkgs, options, ... }: {
  # With an existing `nix.nixPath` entry:
  nix.nixPath = [
    # Add the following to existing entries.
    "nixpkgs-overlays=/etc/nixos/overlays-compat/"
  ];

  # Without any `nix.nixPath` entry:
  nix.nixPath =
    # Prepend default nixPath values.
    options.nix.nixPath.default ++ 
    # Append our nixpkgs-overlays.
    [ "nixpkgs-overlays=/etc/nixos/overlays-compat/" ]
  ;
}

Then, add the following contents to /etc/nixos/overlays-compat/overlays.nix[1]:

self: super:
with super.lib;
let
  # Load the system config and get the `nixpkgs.overlays` option
  overlays = (import <nixpkgs/nixos> { }).config.nixpkgs.overlays;
in
  # Apply all overlays to the input of the current "main" overlay
  foldl' (flip extends) (_: super) overlays self

The /etc/nixos/overlays-compat directory should contain a single overlays.nix file to be understood by the Nix tooling, but the location of this directory can be arbitrary, as long as it is set correctly in the nix.nixPath option.

External Documentation

Python Packages Overlay

Here is an example of Python packages overlay. The trick is to also override python itself with `packageOverrides`.

Github issue with the snippet below: [[1]]

self: super:
# Within the overlay we use a recursive set, though I think we can use `self` as well.
rec {
  # nix-shell -p python.pkgs.my_stuff
  python = super.python.override {
    # Careful, we're using a different self and super here!
    packageOverrides = self: super: {
      my_stuff = super.buildPythonPackage rec {
        pname = "pyaes";
        version = "1.6.0";
        name = "${pname}-${version}";
        src = super.fetchPypi {
          inherit pname version;
          sha256 = "0bp9bjqy1n6ij1zb86wz9lqa1dhla8qr1d7w2kxyn7jbj56sbmcw";
        };
      };
    };
  };
  # nix-shell -p pythonPackages.my_stuff
  pythonPackages = python.pkgs;

  # nix-shell -p my_stuff
  my_stuff = pythonPackages.buildPythonPackage rec {
    pname = "pyaes";
    version = "1.6.0";
    name = "${pname}-${version}";
    src = pythonPackages.fetchPypi {
      inherit pname version;
      sha256 = "0bp9bjqy1n6ij1zb86wz9lqa1dhla8qr1d7w2kxyn7jbj56sbmcw";
    };
  };
}

References

  1. Based on @samueldr's configuration: overlays-compat