How do I apply a GitHub commit to my configuration.nix?

How do I apply a GitHub commit(s) to my configuration.nix? I feel like this is probably a common question, but alas, I’m struggling with it.

Specifically, I had this issue, which someone graciously merged a fix for. I’d like to cherry-pick the fix to test it, but can’t figure out how.

I tried this:

nixpkgs.config.packageOverrides = pkgs: {
  # https://github.com/NixOS/nixpkgs/issues/176484
  pr176561 = import (fetchTarball
    "${nixpkgs-tars}955d1a6dde9862822fbb0f2d6be9bfa51fdbc689.tar.gz")
      { config = config.nixpkgs.config; };
};

It didn’t give any errors, but I’m pretty sure it didn’t apply (it should have modified the pipewire user’s home directory, but did not). Are there logs that confirm whether it was applied? Am I missing something in the above configuration? And, for future reference, does anyone have a complete “how to cherry-pick a GitHub pull request into your NixOS configuration” tutorial/guide?

I tried changing pr176561 = ... to pipewire = ... (…does the name here matter?..) and actually did get an error: error: Dependency is not of a valid type: element 6 of buildInputs for SDL2.

All you are doing here is adding a checkout of that config as a package named pr176561. That doesn’t affect your configuration at all. However the same import statement at nixpkgs.pkgs would work.

Setting { config = config.nixpkgs.config; } there may actually lead to infinite recursion. If it does, simply define your desired nixpkgs config inline.

If you would rather not override your entire configurations nixpkgs, but instead just use this one changed module, you could leave it the way it is and instead disable the module from your configuration’s nixpkgs, and import it from your pr176561 package like so:

{pkgs, ...}: {
  disabledModules = [ "services/desktops/pipewire/pipewire.nix" ];
  imports = [ "${pkgs.pr176561}/nixos/modules/services/desktops/pipewire/pipewire.nix" ];
}

You could even use GitHub’s raw api to fetch just the module file itself, to avoid the large fetch and extra evaluation cost.

On an unrelated note, using packageOverrides directly has been discouraged for a while. Probably better to use overlays, or as some would suggest, just define your custom packages and/or overrides at the call-site.

1 Like

Using flakes:

{
  description = "NixOS configuration";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.05";
    nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
    nixpkgs-pr176561.url = "github:NixOS/nixpkgs/955d1a6dde9862822fbb0f2d6be9bfa51fdbc689"
  }
  outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-pr176561,
    ... }@inputs: {
    let
      nixpkgs = {
        overlays = [
           # Unstable packages overlay
           (final: prev: {
             inherit (import nixpkgs-unstable { system = "x86_64-linux"; })
               ungoogled-chromium firefox-esr
           })
           # Cherry picked overlay
           (final: prev: {
             inherit (import nixpkgs-pr176561 { system = "x86_64-linux"; })
               iosevka;
           })
        ];
      };
    in 
    nixosConfigurations = {
      your-host = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
   (...)
        modules = [
   (...)
}

Regards

2 Likes

However the same import statement at nixpkgs.pkgs would work.

Ok, so, I assume you mean to do:

  imports = [
    (fetchTarball "${nixpkgs-tars}955d1a6dde9862822fbb0f2d6be9bfa51fdbc689.tar.gz") { config = config.nixpkgs.config; }
  ];

This leads to:

error: assertion '(((args) ? localSystem) -> (! ((args) ? system)))' failed

       at /nix/store/i70l6f7f160g0pnf3qd7xv69papg4ad3-source/pkgs/top-level/impure.nix:79:1:

           78| # not be passed, and vice-versa.
           79| assert args ? localSystem -> !(args ? system);
             | ^
           80| assert args ? system -> !(args ? localSystem);
(use '--show-trace' to show detailed location information)

Also, you said:

Setting { config = config.nixpkgs.config; } there may actually lead to infinite recursion. If it does, simply define your desired nixpkgs config inline.

What do you mean by “inline”? Can you show an example?

Also, I tried your other suggestion:

{pkgs, ...}: {
  disabledModules = [ "services/desktops/pipewire/pipewire.nix" ];
  imports = [ "${pkgs.pr176561}/nixos/modules/services/desktops/pipewire/pipewire.nix" ];
}

This leads to:

       at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:496:28:

          495|         builtins.addErrorContext (context name)
          496|           (args.${name} or config._module.args.${name})
             |                            ^
          497|       ) (lib.functionArgs f);
(use '--show-trace' to show detailed location information)
building the system configuration...
error: infinite recursion encountered

This happens even when I’m not setting my original nixpkgs.config.packageOverrides, which means I’m not using { config = config.nixpkgs.config; } anywhere.

actually no, I meant set the value of the nixos module option nixpkgs.pkgs to the import statement you wrote previous, in other words: nixpkgs.pkgs = import someNixpkgs {};.

Inline as in, don’t import it from config.nixpkgs.config. Instead take whatever you have defined for nixpkgs.config elsewhere in your configuration and place it here.

This is probably because of the override. Fortunately there is no real point to exposing this import as a package override at all, so you could probably just remove the override and do imports = let pr176561 = import ... in [ ... ]. For the record, this would probably be the best way to do it as following a PR branch may end up leaving you stagnant for a while until its merged. Better to track a well cached branch like nixos-22.05 or nixos-unstable as your base system and import just this one module.

1 Like

I’m going to be completely honest: I’m a software engineer, I’ve used NixOS for ~1 year, and I barely understand any of what you’ve just said. Clearly I’m not a NixOS power user.

NixOS has for the most part worked out of the box. This is the first time I’ve needed to apply a bug fix. And it sounds like, in order to do so, I’m going to have to sit down, actually read the NixOS docs, and try to become a non-beginner.

1 Like

Well I could always work on my exposition skills, don’t just blame yourself, obviously I’m making things too complicated :laughing:

For now you could probably jus copy this snippet and it would work:

{config, ...}: {
  disabledModules = ["services/desktops/pipewire/pipewire.nix"];
  imports = let
    pr176561 =
      fetchTarball
      "https://github.com/nixos/nixpkgs/archive/955d1a6dde9862822fbb0f2d6be9bfa51fdbc689.tar.gz";
  in ["${pr176561}/nixos/modules/services/desktops/pipewire/pipewire.nix"];
}

All I’m doing is definig the custom nixpkgs in a let block right where it is consumed instead of bothering with modifying the nixpkgs fixed point with an override. There is also no need to import it since all we need is one file from the source tree. I’ll leave pulling just a single file with the GitHub raw api as an optional excercise for you.

2 Likes

Awesome, the patch applied successfully. Thanks!

(Actually, the patch didn’t fix my issue. :sweat_smile: But…I’ll take that convo elsewhere.)

Sorry, this thread is old but exactly what I’m trying to solve. I have a flake with which I’m trying to apply a github commit for one package (davfs2), but am getting an error (see below):

{
  inputs = {
  nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
..... more inputs
  pr73b365.url = "github:nixos/nixpkgs/73b3655f850b7787099675a5beefa19ce2e02274";
  };
  outputs = inputs@{
    self,
    disko,
    nixpkgs,
    nixpkgs-stable,
    pr73b365,
    sops-nix,
    home-manager,
    ...
  }: let
    inherit (self) outputs;
    system = "x86_64-linux";
    nixpkgs = {
      overlays = [
        (final: prev: {
          inherit (import pr73b365 { system = "x86_64-linux"; })
            davfs2;
        })
      ];
    };
  in {
    nixosConfigurations = {
      laptop = nixpkgs.lib.nixosSystem {
        specialArgs = {
           inherit inputs outputs;
        } ;
        modules = [
          ./hosts/laptop/configuration.nix
        ];
     };
......

I’m getting the following error:

❯ sudo nixos-rebuild build --flake .#laptop
building the system configuration...
warning: Git tree '/home/firecat53/nixos/nixos' is dirty
error: attribute 'lib' missing

       at /nix/store/2z6vrv1z25q728gqkcsksi8x963a5vsb-source/flake.nix:70:16:

           69|       };
           70|       laptop = nixpkgs.lib.nixosSystem {
             |                ^
           71|         specialArgs = {

I feel like I’m close but missing something. Any ideas? Thanks!

Before you added that let binding, the nixpkgs came from that splat up above, inputs@{ ... }; it referred to inputs.nixpkgs. Your let binding shadows it so that the later nixpkgs now refers to the one in your let binding, which just has an overlays attribute instead of being a whole nixpkgs flake with a lib output.

Instead of that let binding, just try defining the overlay in your let binding like

let
  davfs2-from-pr = final: prev: { ... };
in
...

and then define an inline NixOS module applying the overlay in your nixosSystem call like

modules = [
  {
    nixpkgs.overlays = [ davfs2-from-pr ];
  }
  ./hosts/laptop/configuration.nix
];

or ditch the let binding entirely and just inline the overlay there as well.

Thanks so much! That worked…except I think what I really need to overlay is the services.davfs2 module, not just the davfs2 package because the module is what I’m trying to test.

I found this example of replacing a module, but the davfs2 module has no packages option.

I appreciate the help! Sorry I didn’t ask the right question to start with.

When there’s no package option in the module, overriding the package in an overlay like you’ve done will suffice as an alternative approach. The pkgs.davfs2 that appears here and here and so on in the module will point to the version from your overlay since you have the overlay applied. (This counts on your overlay including a package of the same name (davfs2). If you’d named the package davfs2-patched in your overlay, the module would reach for davfs2 as usual and still get the old one.)

If you want a newer module as well as a newer package, you can just make those accommodations in your config separately, and they’ll work together.

If you want a newer module as well as a newer package, you can just make those accommodations in your config separately, and they’ll work together.

I’m sorry…I’m struggling to understand what you mean here. I followed your explanation in the first paragraph and I think the following config correctly overrides the package. However, it doesn’t seem to override the service module.

  outputs = inputs@{
    self,
    disko,
    nixpkgs,
    nixpkgs-stable,
    pr73b365,
    sops-nix,
    home-manager,
    ...
  }: let
    inherit (self) outputs;
    system = "x86_64-linux";
  in {
    nixosConfigurations = {
      laptop = nixpkgs.lib.nixosSystem {
        specialArgs = {
          inherit inputs outputs;
        };
        modules = [
          {
            nixpkgs.overlays = [
              (final: prev: {
                inherit (import pr73b365 { system = system; })
                  davfs2;
              })
            ];
          }
          ./hosts/laptop/configuration.nix
        ];
      };

Thanks!

Edit:

The only config I have for the service is services.davfs2.enable = true and then a systemd definition for the mount file. Does that line need to be edited to show that the davfs2 services module should be taken from the pr73b365 input, and if so, how?

There’s an example of module replacement upthread, here. (Here is the relevant section from the NixOS manual.)

There are two parts: disabling the built-in one (that disabledModules line) and adding the version from the PR you want. You can do both in an inline module in side that modules = [...] block. You might as well use the same in-line module you have, so that above your ./hosts/laptop/configuration.nix in the modules list, you have:

{
  nixpkgs.overlays = [
    (final: prev: {
      inherit (import pr73b365 { system = system; })
        davfs2;
    })
  ];
  disabledModules = [ "services/network-filesystems/davfs2.nix" ];
  imports = [ "${pr73b365}/nixos/modules/network-filesystems/davfs2.nix" ];
}
1 Like

Aha, success!! Thanks so much for your patience!

I just had to slightly adjust the paths for the modules (matched the paths from nixpkgs on Github):

disabledModules = [ "services/network-filesystems/davfs2.nix" ];
 imports = [ "${pr73b365}/nixos/modules/services/network-filesystems/davfs2.nix" ];

So…final flake configuration for testing a particular commit for a service module and package:

{
  inputs = {
  nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
..... more inputs
  pr73b365.url = "github:nixos/nixpkgs/73b3655f850b7787099675a5beefa19ce2e02274";
  };
  outputs = inputs@{
    self,
    disko,
    nixpkgs,
    nixpkgs-stable,
    pr73b365,
    sops-nix,
    home-manager,
    ...
  }: let
    inherit (self) outputs;
    system = "x86_64-linux";
  in {
    nixosConfigurations = {
      laptop = nixpkgs.lib.nixosSystem {
        specialArgs = {
           inherit inputs outputs;
        } ;
        modules = [
          {
            nixpkgs.overlays = [
              (final: prev: {
                inherit (import pr73b365 { system = system; })
                  davfs2;
              })
            ];
            disabledModules = [ "services/network-filesystems/davfs2.nix" ];
            imports = [ "${pr73b365}/nixos/modules/services/network-filesystems/davfs2.nix" ];
          }
          ./hosts/laptop/configuration.nix
        ];
     };
   };
}

To just test a commit for a package without the service module, drop the disabledModules and imports = [ "${pr73b365}... lines.

Thanks again @pxc !

1 Like

Oops! I wrote that without testing it and misremembered the paths from when I was looking. I’ve adjusted the text in my example so there’s less for future web searchers to trip over. (Thanks for posting your current config, which is also useful for future searchers.)

1 Like