5

I have a package-upgrades.nix that I use to upgrade packages from unstable or a fork.

{...}:
{
  nixpkgs.config = {
    packageOverrides = let
      pkgsUnstable = import (
        fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-unstable.tar.gz
      ) { };
      pkgsMaster = import (
        fetchTarball https://github.com/NixOS/nixpkgs/archive/master.tar.gz
      ) { };
      pkgsLocal = import (
        fetchTarball https://github.com/moaxcp/nixpkgs/archive/local.tar.gz
      ) { };
    in pkgs:
    rec {
        dropbox = pkgsUnstable.dropbox;
        jbake = pkgsUnstable.jbake;
    };
  };
}

This works well for things like windows manager.

notion = pkgsUnstable.notion;
...
windowManager.notion.enable = true;

The problem is allowUnfree does not seem to get set on the unstable import. I wanted to try something like this.

  pkgsUnstable = import (
    fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-unstable.tar.gz
  ) { inherit config };

This results in an error for an undefined config.

error: undefined variable ‘config’ at /etc/nixos/package-upgrades.nix:7:10
(use ‘--show-trace’ to show detailed location information)
building Nix...
error: undefined variable ‘config’ at /etc/nixos/package-upgrades.nix:7:10
(use ‘--show-trace’ to show detailed location information)
building the system configuration...
error: undefined variable ‘config’ at /etc/nixos/package-upgrades.nix:7:10
(use ‘--show-trace’ to show detailed location information)

Is there any way to override the config in the imported nixpkgs repo?

John Mercier
  • 1,637
  • 3
  • 20
  • 44

1 Answers1

4

You're on the right track. You need to pass a config argument to the Nixpkgs function. However, it is not in scope.

A Nix module is basically a function that evaluates to an attribute set. It's written in Nix and does not get a special treatment, so if you want to reuse something you have defined in a module, you have two options.

  • Introduce a let binding and use that to reference your config
  • Use the config parameter that is passed to NixOS modules

The first option is basic use of the Nix language. The second is more specific to NixOS modules, although it will occur in other places.

When a configuration (conceptually, a set of modules) gets evaluated, the result of the evaluation is passed to all the modules. This is an example of circular programming, where values that have not been computed can be passed around thanks to laziness. It may take some getting used to the idea that the result of a function gets passed as an argument, but it is very useful.

For example, in your case you may be able to use the final value of config as determined by not just this module but all your modules, however, it doesn't work because evaluation of the NixOS configuration seems to be quite strict.

One solution is to factor out the common configuration that all Nixpkgs need to use:

{ config, ...}:
let
  baseConfig = {
    allowUnfree = true;
  };

  pkgsUnstable = import (
    fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-unstable.tar.gz
  ) { config = baseConfig; };
  pkgsMaster = import (
    fetchTarball https://github.com/NixOS/nixpkgs/archive/master.tar.gz
  ) { config = baseConfig; };
  pkgsLocal = import (
    fetchTarball https://github.com/moaxcp/nixpkgs/archive/local.tar.gz
  ) { config = baseConfig; };

in
{
  nixpkgs.config = baseConfig // {
    packageOverrides = pkgs: {
      dropbox = pkgsUnstable.dropbox;
      jbake = pkgsUnstable.jbake;
    };
  };
}

Perhaps it's a good idea to use overlays instead of packageOverrides here. Overlays let you decompose your configuration a bit more. An immediate benefit here is that you may reference your package sets in other modules, because they will be in the pkgs argument so you don't necessarily have to override the packages. Overriding them is a good idea if you want to make sure the same version is used everywhere in your system configuration, but with this you can also reference pkgs.pkgsUnstable.somePackage if you only need that version in a specific situation.

{ ...}:
let

  pkgsConfig = {
    allowUnfree = true;
  };

  packageSetsOverlay = self: super: {
    pkgsUnstable = import (
      fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-unstable.tar.gz
    ) { config = pkgsConfig; };
    pkgsMaster = import (
      fetchTarball https://github.com/NixOS/nixpkgs/archive/master.tar.gz
    ) { config = pkgsConfig; };
    pkgsLocal = import (
      fetchTarball https://github.com/moaxcp/nixpkgs/archive/local.tar.gz
    ) { config = pkgsConfig; };
  };

  upgradesOverlay = self: super: {
    dropbox = super.pkgsUnstable.dropbox;
    jbake = super.pkgsUnstable.jbake;
  };

  overlays = [ packageSetsOverlay
               upgradesOverlay
             ];
in
{
  nixpkgs.overlays = overlays;
  nixpkgs.config = pkgsConfig;
}
Robert Hensing
  • 6,708
  • 18
  • 23
  • Thanks for the help! I am getting an error though. `error: syntax error, unexpected '.', at /etc/nixos/package-upgrades.nix:7:25` – John Mercier Feb 11 '18 at 22:48
  • Also is using an overlay an options? I haven't messed with overlays yet but I was thinking about doing this in an overlay. I'm worried that I would have the same problem though. – John Mercier Feb 11 '18 at 22:49
  • Sorry, I messed up the last line of the snippet but fixed it just now. You should definitely have a look at overlays. They are like `packageOverrides` but more powerful, because you can have multiple overlays instead of just one `packageOverrides` function. Overlays let you split up your overrides nicely. – Robert Hensing Feb 13 '18 at 08:54
  • Ok now I am getting a different error. `error: infinite recursion encountered, at /etc/nixos/package-upgrades.nix:16:9`. This is the line for dropbox. It doesn't seem to have a problem with jbake when I comment out dropbox though. – John Mercier Feb 13 '18 at 11:19
  • 2
    If you can't make the module less [strict](https://en.wikipedia.org/wiki/Strict_function), you can go with the first option of using a `let` binding to do the sharing. I.e. `{ pkgs, ... }: let config = ... in { nixpkgs.config = config;` – Robert Hensing Feb 13 '18 at 11:59
  • I'm still getting the same issue with this. using `let config = config.nixpkgs.config; in` I get ` error: infinite recursion encountered, at /etc/nixos/package-upgrades.nix:3:14` – John Mercier Feb 18 '18 at 19:39
  • You're still using the module system fixed-point to get at your nixpkgs config, which may be the cause of your infinite recursion. In my previous comment I suggested defining the config directly in the let binding instead (at the `...` pseudocode). You can also use `--show-trace` help figure which calls lead to the recursion, although it's usually not so obvious. Anyway, I'll update the answer with some solutions I have tested. – Robert Hensing Feb 20 '18 at 10:27